按非字母顺序、用户定义的字符串值对数组进行排序
Sort array by non-alphabetical, user defined string values
我想以复杂的方式对数组进行排序,但不确定如何进行。这是我正在处理的数据的粗略概念:
[
{ target: random.text.cpu-pct-0, otherData[...] },
{ target: random.text.cpu-pct-1, otherData[...] },
{ target: random.text.cpu-pct-2, otherData[...] },
{ target: random.text.example-0, otherData[...] },
{ target: random.text.example-1, otherData[...] },
{ target: random.text.memory, otherData[...] },
...
]
我希望包含字符串 cpu-pct
的 target
的所有对象排在第一位,然后是包含字符串 memory
的 target
的对象,然后 example
。这个数组可以有任意数量的项目,所以按索引重新排序是行不通的。可能有 1 个对象带有包含 cpu-pct
的 target
,或者可能有 50 多个。我排序的其他字符串也是如此。
我想过遍历原始数组,检查是否存在所需的字符串,将匹配的对象保存到我要查找的每个目标的新数组中,然后在最后合并数组。我认为这可行,但我想有更好、更有效的解决方案,可能使用 usort
,但我不知所措。有什么想法吗?
usort
绝对是正确的选择。这是一种相当通用的方法,您可以扩展 $ranks
数组以包含其他术语,以便根据需要进行排序。
$a = json_decode('[
{ "target": "random.text.cpu-pct-0", "otherData": [1, 2, 3] },
{ "target": "random.text.cpu-pct-1", "otherData": [2, 2, 3] },
{ "target": "random.text.cpu-pct-2", "otherData": [3, 2, 3] },
{ "target": "random.text.example-0", "otherData": [4, 2, 3] },
{ "target": "random.text.example-1", "otherData": [5, 2, 3] },
{ "target": "random.text.memory", "otherData": [6, 2, 3] } ]');
$ranks = array('example' => 0, 'memory' => 1, 'cpu-pct' => 2);
function rank($obj) {
global $ranks;
foreach ($ranks as $key => $value) {
if (strpos($obj->target, $key) !== false) return $value;
}
// sort anything that doesn't match last
return -1;
}
function cmp($a, $b) {
return rank($b) - rank($a);
}
usort($a, "cmp");
print_r($a);
输出:
Array
(
[0] => stdClass Object
(
[target] => random.text.cpu-pct-0
[otherData] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
)
[1] => stdClass Object
(
[target] => random.text.cpu-pct-1
[otherData] => Array
(
[0] => 2
[1] => 2
[2] => 3
)
)
[2] => stdClass Object
(
[target] => random.text.cpu-pct-2
[otherData] => Array
(
[0] => 3
[1] => 2
[2] => 3
)
)
[3] => stdClass Object
(
[target] => random.text.memory
[otherData] => Array
(
[0] => 6
[1] => 2
[2] => 3
)
)
[4] => stdClass Object
(
[target] => random.text.example-0
[otherData] => Array
(
[0] => 4
[1] => 2
[2] => 3
)
)
[5] => stdClass Object
(
[target] => random.text.example-1
[otherData] => Array
(
[0] => 5
[1] => 2
[2] => 3
)
)
)
如果您想进一步对关键字后的值进行排序,您可以将其附加到排名值,然后对组合值进行排序,例如
$ranks = array('cpu-pct', 'memory', 'example');
function rank($obj) {
global $ranks;
foreach ($ranks as $key => $value) {
if (preg_match("/$value(.*)$/", $obj->target, $matches))
return $key . $matches[1];
}
// sort anything that doesn't match last
return 'z';
}
function cmp($a, $b) {
return strcmp(rank($a), rank($b));
}
usort($a, "cmp");
如果要排序的字符串超过 10 个,则需要将 return 值从 rank
更改为 sprintf('%02d', $key) . $matches[1]
以确保排序正常(将 02 替换为 as许多数字,以确保您可以用那么多数字表示所有排序字符串)。
这是一个 usort 方法,您必须为您希望排序的每个可能组合定义条件。希望我的代码评论能给你一些关于方法的提示。
$array = json_decode('[
{ "target": "random.text.cpu-pct-0" },
{ "target": "random.text.cpu-pct-1" },
{ "target": "random.text.cpu-pct-2"},
{ "target": "random.text.example-0" },
{ "target": "random.text.example-1" },
{ "target": "random.text.memory" }
]');
function mySortFunction( $one, $two )
{
$pattern = '/\.(?<label>cpu-pct|example|memory)(?:-(?<value>\d+))?/';
preg_match( $pattern, $one->target, $targetOne );
preg_match( $pattern, $two->target, $targetTwo );
// Both have CPU-PCT? then sort on CPU-PCT-VALUE
if( $targetOne['label'] === 'cpu-pct' and $targetTwo['label'] === 'cpu-pct' )
{
return strcmp( $targetOne['value'], $targetTwo['value'] );
}
// Both have MEMORY? they are the same
if( $targetOne['label'] === 'memory' and $targetTwo['label'] === 'memory' )
{
return 0;
}
// 1 has CPU but 2 has Memory, prefer CPU
if( $targetOne['label'] === 'cpu-pct' and $targetTwo['label'] === 'memory' )
{
return -1;
}
// 1 has MEMORY but 2 has CPI, prefer CPU
if( $targetOne['label'] === 'memory' and $targetTwo['label'] === 'cpu-pct' )
{
return 1;
}
// 1 is MEMORY or CPU, but 2 is Neither
if( $targetOne['label'] === 'cpu-pct' or $targetOne['label'] === 'memory' )
{
if( $targetTwo['label'] !== 'cpu-pct' and $targetTwo['label'] !== 'memory' )
{
return -1;
}
}
// 2 is MEMORY or CPU, but 1 is Neither
if( $targetTwo['label'] === 'cpu-pct' or $targetTwo['label'] === 'memory' )
{
if( $targetOne['label'] !== 'cpu-pct' and $targetOne['label'] !== 'memory' )
{
return 1;
}
}
// ETC
// ETC
// ETC
}
usort( $array, 'mySortFunction' );
我想以复杂的方式对数组进行排序,但不确定如何进行。这是我正在处理的数据的粗略概念:
[
{ target: random.text.cpu-pct-0, otherData[...] },
{ target: random.text.cpu-pct-1, otherData[...] },
{ target: random.text.cpu-pct-2, otherData[...] },
{ target: random.text.example-0, otherData[...] },
{ target: random.text.example-1, otherData[...] },
{ target: random.text.memory, otherData[...] },
...
]
我希望包含字符串 cpu-pct
的 target
的所有对象排在第一位,然后是包含字符串 memory
的 target
的对象,然后 example
。这个数组可以有任意数量的项目,所以按索引重新排序是行不通的。可能有 1 个对象带有包含 cpu-pct
的 target
,或者可能有 50 多个。我排序的其他字符串也是如此。
我想过遍历原始数组,检查是否存在所需的字符串,将匹配的对象保存到我要查找的每个目标的新数组中,然后在最后合并数组。我认为这可行,但我想有更好、更有效的解决方案,可能使用 usort
,但我不知所措。有什么想法吗?
usort
绝对是正确的选择。这是一种相当通用的方法,您可以扩展 $ranks
数组以包含其他术语,以便根据需要进行排序。
$a = json_decode('[
{ "target": "random.text.cpu-pct-0", "otherData": [1, 2, 3] },
{ "target": "random.text.cpu-pct-1", "otherData": [2, 2, 3] },
{ "target": "random.text.cpu-pct-2", "otherData": [3, 2, 3] },
{ "target": "random.text.example-0", "otherData": [4, 2, 3] },
{ "target": "random.text.example-1", "otherData": [5, 2, 3] },
{ "target": "random.text.memory", "otherData": [6, 2, 3] } ]');
$ranks = array('example' => 0, 'memory' => 1, 'cpu-pct' => 2);
function rank($obj) {
global $ranks;
foreach ($ranks as $key => $value) {
if (strpos($obj->target, $key) !== false) return $value;
}
// sort anything that doesn't match last
return -1;
}
function cmp($a, $b) {
return rank($b) - rank($a);
}
usort($a, "cmp");
print_r($a);
输出:
Array
(
[0] => stdClass Object
(
[target] => random.text.cpu-pct-0
[otherData] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
)
[1] => stdClass Object
(
[target] => random.text.cpu-pct-1
[otherData] => Array
(
[0] => 2
[1] => 2
[2] => 3
)
)
[2] => stdClass Object
(
[target] => random.text.cpu-pct-2
[otherData] => Array
(
[0] => 3
[1] => 2
[2] => 3
)
)
[3] => stdClass Object
(
[target] => random.text.memory
[otherData] => Array
(
[0] => 6
[1] => 2
[2] => 3
)
)
[4] => stdClass Object
(
[target] => random.text.example-0
[otherData] => Array
(
[0] => 4
[1] => 2
[2] => 3
)
)
[5] => stdClass Object
(
[target] => random.text.example-1
[otherData] => Array
(
[0] => 5
[1] => 2
[2] => 3
)
)
)
如果您想进一步对关键字后的值进行排序,您可以将其附加到排名值,然后对组合值进行排序,例如
$ranks = array('cpu-pct', 'memory', 'example');
function rank($obj) {
global $ranks;
foreach ($ranks as $key => $value) {
if (preg_match("/$value(.*)$/", $obj->target, $matches))
return $key . $matches[1];
}
// sort anything that doesn't match last
return 'z';
}
function cmp($a, $b) {
return strcmp(rank($a), rank($b));
}
usort($a, "cmp");
如果要排序的字符串超过 10 个,则需要将 return 值从 rank
更改为 sprintf('%02d', $key) . $matches[1]
以确保排序正常(将 02 替换为 as许多数字,以确保您可以用那么多数字表示所有排序字符串)。
这是一个 usort 方法,您必须为您希望排序的每个可能组合定义条件。希望我的代码评论能给你一些关于方法的提示。
$array = json_decode('[
{ "target": "random.text.cpu-pct-0" },
{ "target": "random.text.cpu-pct-1" },
{ "target": "random.text.cpu-pct-2"},
{ "target": "random.text.example-0" },
{ "target": "random.text.example-1" },
{ "target": "random.text.memory" }
]');
function mySortFunction( $one, $two )
{
$pattern = '/\.(?<label>cpu-pct|example|memory)(?:-(?<value>\d+))?/';
preg_match( $pattern, $one->target, $targetOne );
preg_match( $pattern, $two->target, $targetTwo );
// Both have CPU-PCT? then sort on CPU-PCT-VALUE
if( $targetOne['label'] === 'cpu-pct' and $targetTwo['label'] === 'cpu-pct' )
{
return strcmp( $targetOne['value'], $targetTwo['value'] );
}
// Both have MEMORY? they are the same
if( $targetOne['label'] === 'memory' and $targetTwo['label'] === 'memory' )
{
return 0;
}
// 1 has CPU but 2 has Memory, prefer CPU
if( $targetOne['label'] === 'cpu-pct' and $targetTwo['label'] === 'memory' )
{
return -1;
}
// 1 has MEMORY but 2 has CPI, prefer CPU
if( $targetOne['label'] === 'memory' and $targetTwo['label'] === 'cpu-pct' )
{
return 1;
}
// 1 is MEMORY or CPU, but 2 is Neither
if( $targetOne['label'] === 'cpu-pct' or $targetOne['label'] === 'memory' )
{
if( $targetTwo['label'] !== 'cpu-pct' and $targetTwo['label'] !== 'memory' )
{
return -1;
}
}
// 2 is MEMORY or CPU, but 1 is Neither
if( $targetTwo['label'] === 'cpu-pct' or $targetTwo['label'] === 'memory' )
{
if( $targetOne['label'] !== 'cpu-pct' and $targetOne['label'] !== 'memory' )
{
return 1;
}
}
// ETC
// ETC
// ETC
}
usort( $array, 'mySortFunction' );