如何从 php 中的单个数组创建具有相同元素的多个数组?

How to create multiple arrays with same elements from single array in php?

我正在开发一种表单,用户可以在其中上传包含以下数据的文件 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
-------------------------------------------

现在我已将此数据作为 json 数据插入数据库中的一列中。 因此,第一行数据将生成如下:

[{'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': 'INF';'ub': 'INF'; 'value' : '1.4'}].

在上面的示例中,我必须将当前值与下一个值进行比较,如果两者相同,则将创建一个 object 如果我不同,则必须创建第二个 object 等等. lb 表示我必须采用第一个节点的较低频段,ub 表示较高频段。

我将 foreach 与 php 的当前和下一个运算符一起使用,但坚持要创建正确的 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>';
        }
    }

请帮我创建这个场景的逻辑。

$slabs = Array ( 
    [0-300] => 2.5 
    [300-500] => 2.5 
    [500-1000] => 2.5 
    [1000-5000] => 2.5 
    [>5000] => 2.5 
    );

您需要遍历 slabs 数组,每次看到不同的值时输出一个新对象。我已经通过两个功能实现了这一点;第一个 (key_values) 将键拆分为上限和下限,第二个 (convert_slabs) 遍历 $slabs 数组并按值将其拆分为连续区域。

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

测试代码(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;
}

输出:

[{"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

我使用了@Nick 的示例数据,因为它有很好的测试数据,并在我的沙盒演示中将其声明为 $array

第一个棘手的问题是对范围表达式的解析,因为它们的格式不一致。我的代码片段将从字符串的开头 trim 可选的 > ,并将 -INF 附加到字符串的末尾,然后解析该新字符串并仅隔离由分隔的前两个值一个连字符。

接下来,只需跟踪每次迭代之间的值变化即可。当遇到新值时,推送当前范围,然后开始一个新范围。完成迭代后,再压入一个条目,这样最后一个条目就不会从集合中遗漏。

代码:(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']) {
            if ($entry['lb'] !== null) {
                $merged[] = $entry;
            }
            $entry = ['lb' => $lowerBound, 'ub' => $upperBound, 'value' => $value];
        } else {
            $entry['ub'] = $upperBound;
        }
    }
    $merged[] = $entry;
    echo json_encode($merged) . "\n\n";
}

输出:(与@Nick 的数据相同)

[{"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}]