PHP组合和计数关联数组

时间:2012-12-13 20:10:58

标签: php arrays

我们的软件以关联数组的形式提供购买的产品清单。我们需要组合这个数组并创建一个具有合并计数的新数组。然后,该阵列将用于为我们的计费部门创建购买清单。

示例数组:

Array
(
[0] => Array
    (
        [item] => Long Sleeve-Shirt & Hooded Sweatshirt
        [quantity] => 1
        [size] => Youth Small
        [color] => Blue
    )

[1] => Array
    (
        [item] => Long Sleeve-Shirt & Hooded Sweatshirt
        [quantity] => 1
        [size] => Adult Small
        [color] => Red
    )

[2] => Array
    (
        [item] => Hooded Sweatshirt Youth & Adult Sizes
        [quantity] => 1
        [size] => Youth Large
        [color] => Blue
    )
[3] => Array
    (
        [item] => Long Sleeve-Shirt & Hooded Sweatshirt
        [quantity] => 1
        [size] => Youth Small
        [color] => Blue
    )
}

合并数组

Array
(
[0] => Array
    (
        [item] => Long Sleeve-Shirt & Hooded Sweatshirt
        [quantity] => 2
        [size] => Youth Small
        [color] => Blue
    )

[1] => Array
    (
        [item] => Long Sleeve-Shirt & Hooded Sweatshirt
        [quantity] => 1
        [size] => Adult Small
        [color] => Red
    )

[2] => Array
    (
        [item] => Hooded Sweatshirt Youth & Adult Sizes
        [quantity] => 1
        [size] => Youth Large
        [color] => Blue
    )

}

如何创建一个函数来合并第一个数组并创建第二个数组。我唯一能想到的是创建几个foreach循环并慢慢打破列表。我没有使用关联数组和函数,我相信做多个foreach循环会很慢,可以做得更高效。

2 个答案:

答案 0 :(得分:1)

对我而言,就像你没有那么多组合或整合数组而不是删除重复数据一样。问题变成了,你的条件是重复的条件是什么?每个领域都必须完全相同吗?从阅读你的问题看起来是肯定的。由于你在这里嵌套数组(而不是对象数组),听起来像你需要一个很好的哈希算法进行指纹识别。您可以使用PHP native cryptographic hash algorithm,但实际上并不需要它们具有加密安全性。我会看一下murmurhash,但有other options

PHP有一个可以处理这个问题的函数,但它不适用于多维数组:array_unique

您也可以使用类似php哈希表的数组实现为您执行此操作。鉴于你只有4个领域,你可能不会遇到太多问题,但你很可能......

但是你的代码看起来像这样:

// given an array with keys for item (string), size (string) and color (string),
// produce a unique fingerprint value identifying it
function hashProduct(array $product) {
    // Concatenate all the fields of the product array
    $key = $product['item'].$product['size'].$product['color'];

    // Add the length of the key to the end of the hash to reduce collisions
    return ((string)murmurhash($key)) . strlen($key);
}

// Assume $originalArray is passed in populated with the structure you provide above
// Build a consolidated array, selectively adding to it.
public function consolidateProductsList(array $originalArray) {
    $consolidatedArray = array();

    foreach($originalArray as $product) {

        // fingerprint the product
        $hash = hashProduct($product);

        // You could also just do this:
        // $hash = $product['item'].$product['size'].$product['color'];
        // php treats string-type array keys as hash maps

        if(array_key_exits($consolidatedArray[$hash]) {
             // Still a chance of collision here, but it is very small
             // You should try to handle it or at least report it
             $consolidatedArray[$hash]['quantity'] += $product[quantity];
        } else {
            // Product has not been encountered yet
            $consolidatedArray[$hash] = $product;
        }
    }

    return $consolidatedArray;
}

哈希函数中的冲突是您有两个输入生成相同的哈希输出,但彼此不相等。检测它的方法是进行长形式比较,在这种情况下:$product1['item'] === $product2['item'] && $product1['size'] === $product2[size]等。

我没有在PHP中运行甚至检查代码中的错误,但希望它足以让你开始,减去修复我所犯的任何错误或错别字。

答案 1 :(得分:1)

更通用的解决方案是准确定义要分组的字段以及哪个字段应该包含总和:

function consolidate(array $data, array $group_fields, $sum_field)
{
    $res = array();

    foreach ($data as $item) {
        // work out a hash based on the grouped field names
        $hash = '';
        foreach ($group_fields as $field) {
            $hash .= $item[$field];
        }
        // perform summation if item hash matches
        if (isset($res[$hash])) {
            $res[$hash][$sum_field] += $item[$sum_field];
        } else {
            $res[$hash] = $item;
        }
    }

    return array_values($res);
}

print_r(consolidate($data, array('item', 'size', 'color'), 'quantity'));

Demo