I am working on one form where user can upload file with data with below headers.
0-300 | 300-500| 500-1000| 1000-5000|>5000
2.5 | 2.5 | 2.5 | 2.4 | 2.4
1.2 | 1.2 | 1.2 | 1.3 | 1.4
-------------------------------------------
Now i have insert this data in db in one column as a json data. so, for first row data will generate like :
[{'lb' : '0'; 'ub': '1000';'value': '2.5'},
{'lb': '1000';'ub': 'INF'; 'value' : '2.4'}]
and for second row :
[ {'lb' : '0'; 'ub': '1000';'value': '1.2'},
{'lb': '1000';'ub': '5000'; 'value' : '1.3'},
{'lb': 'INF';'ub': 'INF'; 'value' : '1.4'}].
In above example i have to compare current value with next value and if both are same then there will create one object if i got different then i have to create second object and so on. lb means i have to take lower band of first node and ub means upper band.
I am using foreach with current and next operator of php but stuck to create proper objects.
$slabs = //each row from excel.
foreach($slabs as $key => $value) {
$b = $value;
$c = next($slabs) ?? false;
if($b == $c) {
echo '<pre>';
print_r('YES'); stuck here//
echo '</pre>';
}else{
echo '<pre>';
print_r('NO');
echo '</pre>';
}
}
Please help me to create logic on this scenario.
$slabs = Array (
[0-300] => 2.5
[300-500] => 2.5
[500-1000] => 2.5
[1000-5000] => 2.5
[>5000] => 2.5
);
CodePudding user response:
You need to go through your slabs array, outputting a new object every time you see a different value. I've implemented this through two functions; the first (key_values
) splits the key into upper and lower bounds, and the second (convert_slabs
) loops over the $slabs
array and splits it into contiguous regions by value.
function key_values($key) {
if ($key[0] == '>') {
[$lower, $upper] = [substr($key, 1), 'INF'];
}
else {
[$lower, $upper] = explode('-', $key);
}
return [$lower, $upper];
}
function convert_slabs($slabs) {
$bounds = array();
$last_value = reset($slabs);
[$lb, $ub] = [$lower, $upper] = key_values(key($slabs));
while ($value = next($slabs)) {
[$lower, $upper] = key_values(key($slabs));
// new entry required?
if ($value != $last_value) {
$bounds[] = (object)['lb' => $lb, 'ub' => $ub, 'value' => $last_value];
[$lb, $ub] = [$lower, $upper];
$last_value = $value;
}
else {
// no, just extend the upper bound
$ub = $upper;
}
}
// add the last object
$bounds[] = (object)['lb' => $lb, 'ub' => $ub, 'value' => $last_value];
return $bounds;
}
Test code (str_replace
on JSON conversion is just to make output more readable):
$slabs_array = array(
[ '0-300' => 2.5, '300-500' => 2.5, '500-1000' => 2.5, '1000-5000' => 2.4, '>5000' => 2.4 ],
[ '0-300' => 1.2, '300-500' => 1.2, '500-1000' => 1.2, '1000-5000' => 1.3, '>5000' => 1.4 ],
[ '0-300' => 2.5, '300-500' => 2.5, '500-1000' => 2.5, '1000-5000' => 2.5, '>5000' => 2.5 ],
[ '0-300' => 4.5, '300-500' => 2.5, '500-1000' => 2.5, '1000-5000' => 2.5, '>5000' => 3.5 ],
[ '0-300' => 4.5, '300-500' => 3.5, '500-1000' => 3.5, '1000-5000' => 3.5, '>5000' => 3.5 ],
[ '0-300' => 1.5, '300-500' => 2.5, '500-1000' => 2.5, '1000-5000' => 2.5, '>5000' => 1.5 ],
[ '0-300' => 1.5, '300-500' => 2.5, '500-1000' => 3.5, '1000-5000' => 2.5, '>5000' => 3.5 ],
[ '0-300' => 1.5, '300-500' => 2.5, '500-1000' => 2.5, '1000-5000' => 1.5, '>5000' => 1.5 ]
);
foreach ($slabs_array as $slabs) {
$result = convert_slabs($slabs);
echo str_replace('},{', "},\n{", json_encode($result)) . PHP_EOL . PHP_EOL;
}
Output:
[{"lb":"0","ub":"1000","value":2.5},
{"lb":"1000","ub":"INF","value":2.4}]
[{"lb":"0","ub":"1000","value":1.2},
{"lb":"1000","ub":"5000","value":1.3},
{"lb":"5000","ub":"INF","value":1.4}]
[{"lb":"0","ub":"INF","value":2.5}]
[{"lb":"0","ub":"300","value":4.5},
{"lb":"300","ub":"5000","value":2.5},
{"lb":"5000","ub":"INF","value":3.5}]
[{"lb":"0","ub":"300","value":4.5},
{"lb":"300","ub":"INF","value":3.5}]
[{"lb":"0","ub":"300","value":1.5},
{"lb":"300","ub":"5000","value":2.5},
{"lb":"5000","ub":"INF","value":1.5}]
[{"lb":"0","ub":"300","value":1.5},
{"lb":"300","ub":"500","value":2.5},
{"lb":"500","ub":"1000","value":3.5},
{"lb":"1000","ub":"5000","value":2.5},
{"lb":"5000","ub":"INF","value":3.5}]
[{"lb":"0","ub":"300","value":1.5},
{"lb":"300","ub":"1000","value":2.5},
{"lb":"1000","ub":"INF","value":1.5}]
CodePudding user response:
I've used @Nick's sample data since it is has great test data and declared it as $array
in my sandbox demo.
The first squirrelly bit is the parsing of your ranged expressions because they are inconsistently formatted. My snippet will trim the optional >
from the start of the string, and append -INF
to the end of the string, then parse that new string and only isolate the first two values delimited by a hyphen.
Next, it is just a matter of tracking the value changes between each iteration. When a new value is encountered, push the current range, then start a new range. When finished iterating, push one more entry so that the last entry is not omitted from the collection.
Code: (Demo)
$result = [];
foreach ($array as $row) {
$merged = [];
$entry = ['lb' => null, 'ub' => null, 'value' => null];
foreach ($row as $range => $value) {
sscanf(ltrim("$range-INF", '>'), '%[^-]-%[^-]', $lowerBound, $upperBound);
if ($value !== $entry['value']) {
$entry['ub'] = $lowerBound;
if ($entry['lb'] !== null) {
$merged[] = $entry;
}
$entry['lb'] = $lowerBound;
$entry['value'] = $value;
}
}
$entry['ub'] = $upperBound ?? null; // null coalesce to make your IDE happy
$merged[] = $entry;
echo json_encode($merged) . "\n\n";
}
Output: (same data as @Nick's)
[{"lb":"0","ub":"1000","value":2.5},{"lb":"1000","ub":"INF","value":2.4}]
[{"lb":"0","ub":"1000","value":1.2},{"lb":"1000","ub":"5000","value":1.3},{"lb":"5000","ub":"INF","value":1.4}]
[{"lb":"0","ub":"INF","value":2.5}]
[{"lb":"0","ub":"300","value":4.5},{"lb":"300","ub":"5000","value":2.5},{"lb":"5000","ub":"INF","value":3.5}]
[{"lb":"0","ub":"300","value":4.5},{"lb":"300","ub":"INF","value":3.5}]
[{"lb":"0","ub":"300","value":1.5},{"lb":"300","ub":"5000","value":2.5},{"lb":"5000","ub":"INF","value":1.5}]
[{"lb":"0","ub":"300","value":1.5},{"lb":"300","ub":"500","value":2.5},{"lb":"500","ub":"1000","value":3.5},{"lb":"1000","ub":"5000","value":2.5},{"lb":"5000","ub":"INF","value":3.5}]
[{"lb":"0","ub":"300","value":1.5},{"lb":"300","ub":"1000","value":2.5},{"lb":"1000","ub":"INF","value":1.5}]