【问题标题】:Counting distinct values in multidimensional array计算多维数组中的不同值
【发布时间】:2014-04-11 09:31:48
【问题描述】:

我在试图解决这个问题时遇到了真正的问题。

我有一个如下所示的 PHP 数组:

$info = array();

$info[0] = array(
    'car' => 'Audi',
    'previous_car' => 'BMW'
    );

$info[1] = array(
    'car' => 'Audi',
    'previous_car' => 'Seat'
    );

$info[2] = array(
    'car' => 'Audi',
    'previous_carg' => 'BMW'
    );

$info[3] = array(
    'car' => 'BMW',
    'previous_car' => 'BMW'
    );

$info[4] = array(
    'car' => 'Ford',
    'previous_car' => 'Seat'
    );

我需要对此进行一些排序,所以结果如下所示:

Array (
    car [
        'Audi' => 3,
        'BMW' => 1,
        'Ford' => 1
    ],
    previous_car [
        'BMW' => 3,
        'Seat' => 2
    ]

);

我需要计算一个值在同一个键中的不同出现次数,但搜索是在几个数组上进行的。我尝试使用 array_value_count(),但在多维数组上效果不佳。

我试图避免循环,因为如果数组很大,它可能会过大。

我将非常感谢所有的帮助。

【问题讨论】:

标签: php


【解决方案1】:

如果您运行的是 PHP 5.5,则可以使用:

$newArray = array(
    'car' => array_count_values(array_column($info, 'car')),
    'previous_car' => array_count_values(array_column($info, 'previous_car'))
);
var_dump($newArray);

对于 5.5 之前的 PHP 版本

$newArray = array(
    'car' => array_count_values(
        array_map(
            function($value) {
                return $value['car'];
            },
            $info
        )
    ),
    'previous_car' => array_count_values(
        array_map(
            function($value) {
                return $value['previous_car'];
            },
            $info
        )
    )
);
var_dump($newArray);

【讨论】:

  • 不幸的是服务器运行的是 PHP 5.4.9
  • 转储 $newArray 只给出:code array(2) { ["car"]=> array(0) { } ["previous_car"]=> array(0) { } } code
  • 不错的解决方案。谢谢……
【解决方案2】:

以更面向对象的方式,您可以按如下方式解决它

$values = new ArrayObject();
$iterator = new RecursiveArrayIterator($info);
iterator_apply($iterator, 'countDistinct', array($iterator, $values));

function countDistinct($iterator, $values) {
    while ( $iterator -> valid() ) {
        if ( $iterator -> hasChildren() ) {
            countDistinct($iterator -> getChildren(), $values);
        } else {
            if (!$values->offsetExists($iterator->key())) {
                $values->offsetSet($iterator->key(), new ArrayObject());
            }

            if (!$values->offsetGet($iterator->key())->offsetExists($iterator->current())) {
                $values->offsetGet($iterator->key())
                    ->offsetSet($iterator->current(), 1);
            } else {
                $values->offsetGet($iterator->key())
                    ->offsetSet($iterator->current(),
                $values->offsetGet($iterator->key())->offsetGet($iterator->current()) + 1);
            }
        }

        $iterator -> next();
    }
}

当然,在这个例子中你并没有避免循环。但是使用 ArrayObject 和 RecursiveArrayIterator 您将拥有一些内存和性能优势。

这样的结果将与您的预期结果完全匹配,您可以使用 ArrayObject 的 getIterator() 函数轻松地对其进行迭代。

【讨论】:

  • 太棒了!非常感谢!
【解决方案3】:

您可以编写一个对数据进行排序的函数,但现在检查一下: http://www.php.net/manual/en/function.array-multisort.php

【讨论】:

    【解决方案4】:

    以下内容可能对您有所帮助:

    $returnArray = array('car' => NULL, 'previous_car' => NULL);
    
    foreach($info as $newInfo) {
        $returnArray['car'][] = $newInfo['car'];
        $returnArray['previous_car'][] = $newInfo['previous_car'];
    }
    
    $ret['car'] = array_count_values($returnArray['car']);
    $ret['previous_car'] = array_count_values($returnArray['previous_car']);
    
    var_dump($ret);
    

    这会返回:

    array (size=2)
      'car' => 
        array (size=3)
          'Audi' => int 3
          'BMW' => int 1
          'Ford' => int 1
      'previous_car' => 
        array (size=2)
          'BMW' => int 3
          'Seat' => int 2
    

    【讨论】:

    • var_dump of $returnArray 只导致code array(2) { ["car"]=> array(0) { } ["previous_car"]=> array(0) { } }
    • 更新了答案。希望对您有所帮助!
    猜你喜欢
    • 2016-10-13
    • 1970-01-01
    • 2012-07-18
    • 2012-06-26
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多