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