根据聚合的嵌套值将 JSON 排序为 PHP
Sort JSON with PHP based on aggregated nested values
我需要:
- 按每个组合的总价对数组进行排序
。
- Return只有40%总价最高.
$combinations = '[
[ //1st combination
{"id":1,"price":11900},
{"id":2,"price":499},
{"id":3,"price":2099}
],
[ //2nd combination
{"id":1,"price":11900},
{"id":2,"price":499},
{"id":4,"price":999}
],
[ //3rd combination
{"id":1,"price":11900},
{"id":2,"price":499},
{"id":5,"price":899}
],
[ //4th combination
{"id":1,"price":11900},
{"id":2,"price":499},
{"id":6,"price":2999}
]
]';
<?php
$json = json_decode('[
[{"id":1,"price":11900},{"id":2,"price":499},{"id":3,"price":2099}],
[{"id":1,"price":11900},{"id":2,"price":499},{"id":4,"price":999}],
[{"id":1,"price":11900},{"id":2,"price":499},{"id":5,"price":899}],
[{"id":1,"price":11900},{"id":2,"price":499},{"id":6,"price":2999}]
]');
// var_dump($json);
// ($a, $b) for ASC sorting
// ($b, $a) for DESC sorting
usort($json, function ($b, $a) {
$a_prices = 0;
foreach($a as $aa)
$a_prices += $aa->price;
$b_prices = 0;
foreach($b as $bb)
$b_prices += $bb->price;
return $a_prices - $b_prices;
});
// Find where 40% stops
// It is up to you to choose between round(), ceil() or floor()
$breakpoint = round(sizeof($json) * 40 / 100);
$sorted_chunk = array_slice($json, 0, $breakpoint);
var_dump($sorted_chunk);
虽然@medilies 的回答简单而正确,但这里有一种更经济的数据排序方法。如果我们使用的是大型数据集,straight-up usort
可能会变得相当昂贵——因为每个 $a
与 [= 的比较值必须是 re-calculated 13=]比较。我们可以改为计算总和 up-front 并使用“缓存”值进行比较。
// Here's the data; decoded as an array:
$json = json_decode('[
[{"id":1,"price":11900},{"id":2,"price":499},{"id":3,"price":2099}],
[{"id":1,"price":11900},{"id":2,"price":499},{"id":4,"price":999}],
[{"id":1,"price":11900},{"id":2,"price":499},{"id":5,"price":899}],
[{"id":1,"price":11900},{"id":2,"price":499},{"id":6,"price":2999}]
]', true);
// Calculate the sums for all prices per row up-front.
// Map array into sums: Get the sum for each row's "price" columns
$sums = array_map(fn($v) => array_sum(array_column($v, 'price')), $json);
// Use $sums in our key-based sorter for the comparison values:
uksort($json, function($b, $a) use ($sums) {
return $sums[$a] <=> $sums[$b];
});
// See the sums, get the sorted data:
var_dump($sums, $json);
这里我们使用uksort
而不是usort
,因为我们只需要知道被排序的数组成员的键。我们的“比较缓存”或 $sums
数组,其键与目标数组匹配,与 use()
一起传递到排序函数中。在函数内部,我们只是比较$sums[$a]
和$sums[$b]
中的匹配值,不重复求和计算。演示:https://3v4l.org/sNluJ#v8.1.3
在这种情况下,需要 大 数据集才能产生显着差异。如果需要更昂贵的迭代(例如,多次“重”函数调用)才能获得要比较的值,则“up-front 且仅一次”评估将节省很多不必要的计算周期。
关于返回 OP 想要的最终前 40% 结果,请参考已接受的答案。
我需要:
- 按每个组合的总价对数组进行排序 。
- Return只有40%总价最高.
$combinations = '[
[ //1st combination
{"id":1,"price":11900},
{"id":2,"price":499},
{"id":3,"price":2099}
],
[ //2nd combination
{"id":1,"price":11900},
{"id":2,"price":499},
{"id":4,"price":999}
],
[ //3rd combination
{"id":1,"price":11900},
{"id":2,"price":499},
{"id":5,"price":899}
],
[ //4th combination
{"id":1,"price":11900},
{"id":2,"price":499},
{"id":6,"price":2999}
]
]';
<?php
$json = json_decode('[
[{"id":1,"price":11900},{"id":2,"price":499},{"id":3,"price":2099}],
[{"id":1,"price":11900},{"id":2,"price":499},{"id":4,"price":999}],
[{"id":1,"price":11900},{"id":2,"price":499},{"id":5,"price":899}],
[{"id":1,"price":11900},{"id":2,"price":499},{"id":6,"price":2999}]
]');
// var_dump($json);
// ($a, $b) for ASC sorting
// ($b, $a) for DESC sorting
usort($json, function ($b, $a) {
$a_prices = 0;
foreach($a as $aa)
$a_prices += $aa->price;
$b_prices = 0;
foreach($b as $bb)
$b_prices += $bb->price;
return $a_prices - $b_prices;
});
// Find where 40% stops
// It is up to you to choose between round(), ceil() or floor()
$breakpoint = round(sizeof($json) * 40 / 100);
$sorted_chunk = array_slice($json, 0, $breakpoint);
var_dump($sorted_chunk);
虽然@medilies 的回答简单而正确,但这里有一种更经济的数据排序方法。如果我们使用的是大型数据集,straight-up usort
可能会变得相当昂贵——因为每个 $a
与 [= 的比较值必须是 re-calculated 13=]比较。我们可以改为计算总和 up-front 并使用“缓存”值进行比较。
// Here's the data; decoded as an array:
$json = json_decode('[
[{"id":1,"price":11900},{"id":2,"price":499},{"id":3,"price":2099}],
[{"id":1,"price":11900},{"id":2,"price":499},{"id":4,"price":999}],
[{"id":1,"price":11900},{"id":2,"price":499},{"id":5,"price":899}],
[{"id":1,"price":11900},{"id":2,"price":499},{"id":6,"price":2999}]
]', true);
// Calculate the sums for all prices per row up-front.
// Map array into sums: Get the sum for each row's "price" columns
$sums = array_map(fn($v) => array_sum(array_column($v, 'price')), $json);
// Use $sums in our key-based sorter for the comparison values:
uksort($json, function($b, $a) use ($sums) {
return $sums[$a] <=> $sums[$b];
});
// See the sums, get the sorted data:
var_dump($sums, $json);
这里我们使用uksort
而不是usort
,因为我们只需要知道被排序的数组成员的键。我们的“比较缓存”或 $sums
数组,其键与目标数组匹配,与 use()
一起传递到排序函数中。在函数内部,我们只是比较$sums[$a]
和$sums[$b]
中的匹配值,不重复求和计算。演示:https://3v4l.org/sNluJ#v8.1.3
在这种情况下,需要 大 数据集才能产生显着差异。如果需要更昂贵的迭代(例如,多次“重”函数调用)才能获得要比较的值,则“up-front 且仅一次”评估将节省很多不必要的计算周期。
关于返回 OP 想要的最终前 40% 结果,请参考已接受的答案。