如何在一个键值不同的php数组中查找和删除几乎重复的行?
Posted
技术标签:
【中文标题】如何在一个键值不同的php数组中查找和删除几乎重复的行?【英文标题】:How find and delete almost duplicate rows in php array, which differ in one key value? 【发布时间】: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和空值,当事件发生时,新行被添加值,但旧的空值保留。
如果(对于相同的id
、timestamp
和name
)它们都具有null
值,则应该删除哪个项目?
数组键(行)应该被移除。有哪只!重复的 id、时间戳、名称但值为 null
【参考方案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);
参考见:
http://php.net/manual/en/function.array-reduce.php http://php.net/manual/en/function.array-filter.php例如,请参阅:
https://3v4l.org/Toq75【讨论】:
太棒了,它有效!非常感谢,@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);
【讨论】:
以上是关于如何在一个键值不同的php数组中查找和删除几乎重复的行?的主要内容,如果未能解决你的问题,请参考以下文章