2017-08-28 85 views
1

我有以下阵列(阵列大):如何查找和删除php数组中几乎重复的行,这些行在一个键值上有所不同?

Array ( 
    [0] => Array ( 
       [id] => 1 
       [timestamp] => 1503050400 
       [name] => Event A 
       [value] => ) 
    [1] => Array ( 
       [id] => 2 
       [timestamp] => 1503446400 
       [name] => Event B 
       [value] => ) 
    [2] => Array ( 
       [id] => 2 
       [timestamp] => 1503446400 
       [name] => Event B 
       [value] => 71) 
    [3] => Array ( 
       [id] => 3 
       [timestamp] => 1503720000 
       [name] => Event C 
       [value] => 12) 
    [4] => Array ( 
       [id] => 3 
       [timestamp] => 1503720000 
       [name] => Event C 
       [value] => ) 

       ... 
) 

正如你可以看到,一些阵列键(行)具有相同的ID,时间戳和名称,但不同的价值。 我想找到并取消设置满足以下条件的行($ array [$ key]):

如果数组的键具有相同的名称,Id和时间戳,请删除此键,但只保留Value! = NULL

看起来像这样:

foreach ($array as $key => $row) { 
    if (...) { 
    unset($array[$key]); 
    } 
else {} 

} 
print_r($array); 

输出应该是:

Array ( 
    [0] => Array ( 
       [id] => 1 
       [timestamp] => 1503050400 
       [name] => Event A 
       [value] => ) 
    [2] => Array ( 
       [id] => 2 
       [timestamp] => 1503446400 
       [name] => Event B 
       [value] => 71) 
    [3] => Array ( 
       [id] => 3 
       [timestamp] => 1503720000 
       [name] => Event C 
       [value] => 12) 

       ... 
) 
+1

为什么不直接过滤那些拥有空'value'项目? – RomanPerekhrest

+0

因为这是一个动态数组,所以在时间表中有一个Id,Name,Timestamp和空值,当事件发生时,新行添加了值,但旧值与空值保留。 –

+0

如果(对于同一个'id','timestamp'和'name')它们都具有'null'值,哪个项目应该被删除? – localheinz

回答

1

可以使用array_reduce()array_filter()

<?php 

$data = array(
    array(
     'id' => 1, 
     'timestamp' => 1503050400, 
     'name' => 'Event A', 
     'value' => null, 
    ), 
    array(
     'id' => 2, 
     'timestamp' => 1503446400, 
     'name' => 'Event B', 
     'value' => null, 
    ), 
    array(
     'id' => 2, 
     'timestamp' => 1503446400, 
     'name' => 'Event B', 
     'value' => 71, 
    ), 
    array(
     'id' => 3, 
     'timestamp' => 1503720000, 
     'name' => 'Event C', 
     'value' => 12, 
    ), 
    array(
     'id' => 3, 
     'timestamp' => 1503720000, 
     'name' => 'Event C', 
     'value' => null, 
    ), 
); 

/** 
* Reduce the array of items to an array of buckets, where 
* each bucket contains elements with the same 
* 
* - id 
* - timestamp 
* - name 
* 
* so that we can than take a look at the contents of the 
* individual buckets. 
*/ 
$buckets = array_reduce(
    $data, 
    function (array $carry, array $item) { 
     /** 
     * create an index from 
     * 
     * - id 
     * - timestamp 
     * - name 
     */ 
     $index = serialize(array(
      'id' => $item['id'], 
      'timestamp' => $item['timestamp'], 
      'name' => $item['name'], 
     )); 

     /** 
     * initialize empty bucket if we don't have one yet for this index 
     */ 
     if (!array_key_exists($index, $carry)) { 
      $carry[$index] = array(); 
     } 

     /** 
     * add item to bucket 
     */ 
     $carry[$index][] = $item; 

     return $carry; 
    }, 
    array() 
); 

/** 
* Reduce the content of the buckets to elements that match the requirements. 
*/ 
$filtered = array_reduce(
    $buckets, 
    function (array $carry, array $items) { 
     /** 
     * if we have only one item in the bucket, let's take it 
     */ 
     if (1 === count($items)) { 
      $carry[] = array_shift($items); 

      return $carry; 
     } 

     /** 
     * find all items where the value is not null 
     */ 
     $withoutNullValue = array_filter($items, function (array $item) { 
      return array_key_exists('value', $item) && null !== $item['value']; 
     }); 

     /** 
     * if we have any items where the value is not null, take all of them 
     */ 
     if (0 < count($withoutNullValue)) { 
      $carry = array_merge(
       $carry, 
       $withoutNullValue 
      ); 

      return $carry; 
     } 

     /** 
     * if all of the items have a value of null, let's just take the first 
     */ 
     $carry[] = array_shift($items); 

     return $carry; 
    }, 
    array() 
); 

var_dump($filtered); 

为了参考,见:

有关示例,请参见:

+0

令人惊叹的,它的工作原理!非常感谢,@localheinz!如此复杂,我认为应该容易得多。 –

+0

很高兴你喜欢它,@Anton_Dev!问题是我们需要迭代两次:1)填充桶和2)然后检查它们。我们无法确定数组中的任何项目是否可以保留或需要执行,直到将它们抛入桶中。 – localheinz

0
foreach ($array as $key => $row) { 
    if ($row[value]) { 
    unset($array[$key]); 
    } 
else { 
    $row[result] = $row[value]; 
    unset($row[value]); 
    } 
} 
print_r($array); 
+0

介意解释你的代码? –

相关问题