【问题标题】:PHP sort array by subsetPHP按子集排序数组
【发布时间】:2011-09-23 21:07:06
【问题描述】:

我有两个数组。

一个是更大的数据位:

Array
(
    [12] => blah
    [36] => foo
    [58] => blah
    [60] => blah
    [72] => blah
    [90] => bar
)

另一个是按不同顺序排列的不同但相关数据的较小子集,每个键对应于较大数组中的相同键:

Array
(
    [36] => foo data
    [90] => bar data
    [12] => blah data
)

现在,我的问题是,如何让第一个数组按这样的顺序排列,以便第一个数组中的键在第二个数组中具有相应的键将首先出现,并且与第二个数组的顺序相同?

因此,像这样:

Array
(
    [36] => foo
    [90] => bar
    [12] => blah
    [58] => blah
    [60] => blah
    [72] => blah
)

【问题讨论】:

  • 我不知道,但 +1 为用户名...
  • array_sort 可能对你有用
  • 您可能必须使用uksort,但我认为不使用闭包有点困难。您使用的是哪个 PHP 版本?

标签: php arrays sorting subset


【解决方案1】:

使用uksort

编辑: 修复了 malko 指出的语法/逻辑错误。谢谢。

$array_to_sort = array
(
    12 => "blah",
    36 => "foo",
    58 => "blah",
    60 => "blah",
    72 => "blah",
    90 => "bar"
);

$sorted_array = array(
    36 => "foo data",
    90 => "bar data",
    12 => "blah data"
);

global $sorted_array_keys;
$sorted_array_keys = array_keys($sorted_array);

function cmp($a, $b)
{
    global $sorted_array_keys;
    $a_in_array = in_array($a, $sorted_array_keys);
    $b_in_array = in_array($b, $sorted_array_keys);
    if ($a_in_array && $b_in_array) {
        return array_search($a, $sorted_array_keys) - array_search($b, $sorted_array_keys);
    } else if ( $a_in_array ) {
        return -1;
    } else {
        return 1;
    }
}

uksort ( $array_to_sort , cmp );
print_r($array_to_sort);

这开始时干净利落,但最终变得非常丑陋和不清楚。我现在倾向于其他一些答案,而不是我的。

【讨论】:

  • 抱歉我的投票不好(删除它)是的可能是一个解决方案,但你应该提供更多细节。
  • @malko - 我刚刚发布了一个应该按照要求做的例子。
  • @jacobs,这不起作用的原因之一是函数 cmp 根本不知道 $keys。请参阅我的帖子以查看 uksort 的工作示例(使用“closure”和“use”让比较函数知道 $keys)
  • @malko 啊。我忘记了php范围。我通常在 as3 中工作,它对闭包有很好的支持。但是,php 应该与全局一起使用。见编辑。
  • @jacobs,更正语法将导致返回:Array ([12] => blah [90] => bar [72] => blah [58] => blah [36] => foo [60] => blah ) 不是我们想要的
【解决方案2】:
$array1 = array(12 => 1, 36 => 2, 58 => 3, 60 => 4, 72 => 5);
$array2 = array(36 => 1, 60 => 2, 12 => 1);

# obtaining keys in the order of question    
$result = array_intersect_key($array2, $array1);

# assign values from original $array1
foreach($result as $key => &$value) {
    $value = $array1[$key];
}
unset($value); # kill reference for safety

# add missing elements from $array1
$result += $array1;

var_dump($result);

输出:

array(5) {
  [36]=>
  int(2)
  [60]=>
  int(4)
  [12]=>
  int(1)
  [58]=>
  int(3)
  [72]=>
  int(5)
}

请参阅Array Operators 了解+ 了解数组。

【讨论】:

    【解决方案3】:

    这是一个使用带有闭包的 uksort 的示例,我认为它在大型数组上应该更有效,但我没有做过任何基准测试,所以......很难真正确认没有测试。

    $a = array(
        12 => 'blah'
        ,36 => 'foo'
        ,58 => 'blah'
        ,60 => 'blah'
        ,72 => 'blah'
        ,90 => 'bar'
    );
    
    $b = array(
        36 => 'foo data'
        ,90 => 'bar data'
        ,12 => 'blah data'
    );
    
    $keysPosition = array_flip(array_keys($b));
    uksort($a,function($a,$b) use ($keysPosition){
        if(isset($keysPosition[$a],$keysPosition[$b])){
            return $keysPosition[$a]>$keysPosition[$b]?1:-1;
        }else if( isset($keysPosition[$a]) ){
            return -1;
        }else if( isset($keysPosition[$b]) ){
            return 1;
        }
        return 0;
    });
    
    print_r($a);
    

    结果:

    Array
    (
        [36] => foo
        [90] => bar
        [12] => blah
        [72] => blah
        [58] => blah
        [60] => blah
    )
    

    如果您不能使用闭包(php

    【讨论】:

      【解决方案4】:

      简单的 O(n) 解决方案。

      $arr1 = array(12 => 1, 36 => 2, 58 => 3, 60 => 4, 72 => 5);
      $arr2 = array(36 => 1, 60 => 2, 12 => 1);
      
      $result = array();
      
      foreach($arr2 as $key => $value) {
          $result[$key] = $arr1[$key];
          unset($arr1[$key]);
      }
      
      foreach($arr1 as $key => $value) {
          $result[$key] = $arr1[$key];
      }
      
      var_dump($result);
      

      输出:

      array(5) {
        [36]=>
        int(2)
        [60]=>
        int(4)
        [12]=>
        int(1)
        [58]=>
        int(3)
        [72]=>
        int(5)
      }
      

      【讨论】:

      • 即将发布大致相同的内容;)
      • 无需取消设置值,也无需复制另一个 for-each 中的所有重复项。
      猜你喜欢
      • 1970-01-01
      • 2011-01-29
      • 2011-04-14
      • 2013-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-18
      • 1970-01-01
      相关资源
      最近更新 更多