Home > Software engineering >  How to create multiple arrays with same elements from single array in php?
How to create multiple arrays with same elements from single array in php?

Time:06-01

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}]

Demo on 3v4l.org

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}]
  • Related