2012-12-13 208 views
-2

我們的軟件在關聯數組中提供購買的產品列表。我們需要組合這個數組並創建一個具有統一計數的新數組。然後,此陣列將用於爲我們的結算部門創建採購清單。PHP組合並計數關聯數組

樣本數組:

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循環會很慢,並且可以做得更有效率。

+5

這很好。你試過什麼了? –

+0

有沒有問題?人們怎麼回答?我可以幫你解決,但我不明白你想做什麼。 – Ms01

回答

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錯誤的代碼,但我希望它足以讓你開始,減去固定什麼錯誤或我犯的錯別字。

+0

經過一堆修正後,就像一個魅力。感謝這個偉大的例子。 –

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