-2

当社のソフトウェアは、連想配列で購入した製品リストを提供します。この配列を組み合わせて、統合されたカウントを持つ新しい配列を作成する必要があります。この配列は、請求部門の購入リストを作成するために使用されます。

サンプル配列:

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
    )

}

最初の配列を結合して2番目の配列を作成する関数を作成するにはどうすればよいですか。私が考えることができる唯一のことは、いくつかの foreach ループを作成し、ゆっくりとリストを分割することです。私は連想配列と関数を扱ったことがなく、複数の foreach ループを実行すると時間がかかり、はるかに効率的に実行できると思います。

4

2 に答える 2

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'));

デモ

于 2012-12-14T01:41:17.567 に答える
1

配列を組み合わせたり統合したりするのではなく、重複を削除しているように思えます。問題は、エントリが重複する条件は何ですか? すべてのフィールドがまったく同じである必要がありますか? あなたの質問を読むと、はいのように見えます。ここでは (オブジェクトの配列とは対照的に) 配列をネストしているため、フィンガープリンティングには優れたハッシュ アルゴリズムが必要なように思えます。PHP ネイティブの暗号化ハッシュ アルゴリズムを使用することもできますが、暗号的に安全である必要はありません。私ならmurmurhashを見てみますが、他にも選択肢があります。

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;
}

ハッシュ関数の衝突は、同じハッシュ出力を生成する 2 つの入力があるが、互いに等しくない場合です。それを検出する方法は、長い形式の比較を行うことです。この場合は次のようになります$product1['item'] === $product2['item'] && $product1['size'] === $product2[size]

私はそのコードを実行したり、php のエラーをチェックしたりしていませんが、バグやタイプミスを修正することを除いて、始めるのに十分であることを願っています.

于 2012-12-13T20:58:35.983 に答える