【问题标题】:Array sort by key where keys are clothes sizes (S, M, L, etc.)数组按键排序,其中键是衣服尺寸(S、M、L 等)
【发布时间】:2021-07-13 10:56:44
【问题描述】:

我有一个数组,它的键是大小,值是 'in-stock''no-stock'

示例数组:

$data = [
    'L' => 'in-stock',
    'S' => 'in-stock',
    'XL' => 'no-stock',
    'M' => 'in-stock',
];

我正在尝试按大小对其进行排序。预期输出为:

$data = [
    'S' => 'in-stock',
    'M' => 'in-stock',
    'L' => 'in-stock',
    'XL' => 'no-stock',
];

我一直在研究其他类似的问题,但没有成功,因为它们具有不同的数组结构。

我正在努力使用 uksort 函数,因为我想要对数组进行排序并保留键。

uksort($data, function($a, $b) use ($data) {
    static $sizes;
    // filter out only used size values => ['S', 'M', 'L', 'XL']
    $sizes = array_filter(["XXS", "XS", "S", "M", "L", "XL", "XXL", "XXXL"], function($arr) use ($data) {
        return array_key_exists($arr, $data);
    });       

    $sizes = array_values($sizes);  

    if (array_search($a, $sizes) === array_search($b, array_keys($data))) {
        return 0;
    }      
    if (array_search($a, $sizes) < array_search($b, array_keys($data))) {
        return -1;
    }      
    if (array_search($a, $sizes) > array_search($b, array_keys($data))) {
        return 1;
    }      

});

结果:

Array
(
    [S] => in-stock
    [L] => in-stock
    [XL] => in-stock
    [M] => in-stock
)

我正在尝试比较 $data 中的关键位置并在 $sizes 中定义排序顺序。它不起作用,我正在努力完全理解如何在uksort 回调中正确比较$a$b

https://www.php.net/manual/en/function.uksort.php

如果认为第一个参数分别小于、等于或大于第二个参数,则比较函数必须返回一个小于、等于或大于零的整数。 p>

【问题讨论】:

    标签: php arrays sorting


    【解决方案1】:

    如果您有一个明确的顺序,请不要将其用于排序,而是用于映射。例如:

    $data = [
        'L' => 'in-stock',
        'S' => 'in-stock',
        'XL' => 'no-stock',
        'M' => 'in-stock',
    ];
    
    function getOrderedBySize(array $data): array {
        $result = [];
        foreach (["XXS", "XS", "S", "M", "L", "XL", "XXL", "XXXL"] as $key) {
            if (array_key_exists($key, $data)) {
                $result[$key] = $data[$key];
            }
        }
    
        return $result;
    }
    
    print_r($data);
    print_r(getOrderedBySize($data));
    

    虽然如果你绝对想对输入数组进行排序,这样做可以:

    $fixedOrder = array_flip(["XXS", "XS", "S", "M", "L", "XL", "XXL", "XXXL"]);
    
    uksort($data, static fn(string $a, string $b): int => $fixedOrder[$a] <=> $fixedOrder[$b]);
    
    print_r($data);
    

    【讨论】:

    • 您的代码在小情况下将无法工作,请使用 strtoupper 函数
    • 问题中没有迹象表明小写键是一回事。
    【解决方案2】:

    你需要使用uasort函数(user-associative-sort),而不是uksort。

    uasort($array, function($a, $b) {
        return $a >= $b;
    });
    

    该函数将接收两个项目。

    因此,在更复杂的情况下,假设您要对格式的行进行排序

    [ '大小' => 'L', '名称' => 'Xyzzy' ]

    你会的

    uasort($array, function($row1, $row2) {
        $keys = [ 'size' => 1, 'name' => -1 ];
        foreach ($keys as $name => $order) {
            if ($row1[$name] < $row2[$name]) {
                 return $order;
            }
            if ($row1[$name] === $row2[$name]) {
                 continue;
            }
            return -1*$order;
        }
        return 0;
    });
    

    这将允许一个键升序排序,然后另一个键降序。您可以将其包装在不同的函数中:

    function flexsort(&$array, $order) {
    uasort($array, function($row1, $row2) use($order) {
        foreach ($order as $name => $order) {
            if ($row1[$name] < $row2[$name]) {
                 return $order;
            }
            if ($row1[$name] === $row2[$name]) {
                 continue;
            }
            return -1*$order;
        }
        return 0;
    });
    };
    

    然后:

    flexsort($allRows,[ 'size' => 1, 'name' => -1 ]);
        
    

    【讨论】:

      猜你喜欢
      • 2019-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-27
      • 1970-01-01
      • 1970-01-01
      • 2019-03-27
      • 1970-01-01
      相关资源
      最近更新 更多