【问题标题】:How find and delete almost duplicate rows in php array, which differ in one key value?如何在一个键值不同的php数组中查找和删除几乎重复的行?
【发布时间】:2018-02-05 18:06:36
【问题描述】:

我有以下数组(数组很大):

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 )

              ...
)

【问题讨论】:

  • 为什么不只过滤那些有空value的项目?
  • 因为这是一个动态数组,调度中有一个Id,Name,Timestamp和空值,当事件发生时,新行被添加值,但旧的空值保留。
  • 如果(对于相同的idtimestampname)它们都具有null 值,则应该删除哪个项目?
  • 数组键(行)应该被移除。有哪只!重复的 id、时间戳、名称但值为 null

标签: php arrays foreach filter unset


【解决方案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);

参考见:

例如,请参阅:

【讨论】:

  • 太棒了,它有效!非常感谢,@localheinz!如此复杂,我认为应该容易得多。
  • 很高兴你喜欢它,@Anton_Dev!问题是我们需要迭代两次:1)填充桶和 2)然后检查它们。在我们将它们扔进桶之前,我们无法真正判断数组中的任何项目是否可以保留或需要离开。
【解决方案2】:
foreach ($array as $key => $row) {
  if ($row[value]) {
    unset($array[$key]);
  }
else {
  $row[result] = $row[value];
  unset($row[value]);
  }
}
print_r($array);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-01
    • 1970-01-01
    • 2011-06-01
    • 2014-11-05
    • 1970-01-01
    • 2019-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多