Я работаю с большими наборами данных, и мне нужно объединить массивы, когда они дублируются. Если они объединяются, мне нужен счет, добавленный в массив.
array:3721 [▼
0 => array:3 [▼
"subscriber" => "gmail.com."
"code" => 554
"status" => 50
]
1 => array:3 [▼
"subscriber" => "apied.be"
"code" => 550
"status" => 51
]
2 => array:3 [▼
"subscriber" => "beton-dobbelaere.be"
"code" => 550
"status" => 50
]
3 => array:3 [▼
"subscriber" => "live.be"
"code" => 550
"status" => 51
]
4 => array:3 [▼
"subscriber" => "hotmail.be"
"code" => 550
"status" => 51
]
5 => array:3 [▼
"subscriber" => "telenet.be"
"code" => 550
"status" => 50
]
6 => array:3 [▼
"subscriber" => "telenet.be"
"code" => 550
"status" => 55
]
7 => array:3 [▼
"subscriber" => "telenet.be"
"code" => 550
"status" => 51
]
8 => array:3 [▼
"subscriber" => "telenet.be"
"code" => 550
"status" => 51
]
Это должно выглядеть примерно так:
array:3721 [▼
0 => array:3 [▼
"subscriber" => "gmail.com."
"code" => 554
"status" => 50
"amount" => 1
]
1 => array:3 [▼
"subscriber" => "apied.be"
"code" => 550
"status" => 51
"amount" => 1
]
2 => array:3 [▼
"subscriber" => "beton-dobbelaere.be"
"code" => 550
"status" => 50
"amount" => 1
]
3 => array:3 [▼
"subscriber" => "live.be"
"code" => 550
"status" => 51
"amount" => 1
]
4 => array:3 [▼
"subscriber" => "hotmail.be"
"code" => 550
"status" => 51
"amount" => 1
]
5 => array:3 [▼
"subscriber" => "telenet.be"
"code" => 550
"status" => 50
"amount" => 1
]
6 => array:3 [▼
"subscriber" => "telenet.be"
"code" => 550
"status" => 55
"amount" => 1
]
7 => array:3 [▼
"subscriber" => "telenet.be"
"code" => 550
"status" => 51
"amount" => 2
]
Когда я объединил этот пример, используя
array_unique($hardbounces, SORT_REGULAR);
Мне оставалось около 534 результатов вместо 3721, это здорово, мне тоже нужно знать сумму, и она должна быть несколько эффективной, потому что результирующие наборы могут быть очень большими (намного больше).
После того, как его нужно будет также отсортировать по доменам и количествам.
Я использую laravel 5.1, если необходимо, я могу превратить массив в коллекцию, поэтому доступны вспомогательные функции
Мне удалось исправить это с помощью цикла foreach, который работает быстрее, чем я ожидал (0.3179 секунд)
$merged = [];
foreach($hardbounces as &$hardbounce){
if(empty($merged)){
$merged[] = $hardbounce;
}else{
$i = 0;
foreach($merged as $key => $merge){
$i++;
if($hardbounce['subscriber'] == $merge['subscriber'] && $hardbounce['code'] == $merge['code'] && $hardbounce['status'] == $merge['status']){
$merged[$key]['amount']++;
break;
}
if(count($merged) == $i){
$merged[] = $hardbounce;
}
}
}
}
Я прохожу через отскоки, если слитый пуст (первая итерация), он просто добавляет hardbounce. С этого момента я буду перебирать новый массив и проверять, есть ли дубликат. Когда это происходит, мы просто добавляем его к сумме и выходим из foreach. В противном случае он в конечном итоге все равно добавит дубликаты. После того, как я проверю, дошли ли мы до последней итерации, а это значит, что если он еще не сломался, мы должны добавить hardbounce, потому что он еще не существует.
Чтобы быть ясным, я убедился, что количество 1 уже существует до запуска этого цикла, вместо того, чтобы добавлять его во время этого цикла.
Пытаться
<?php
$input = array(
0 => array(
"subscriber" => "gmail.com.",
"code" => 554,
"status" => 50),
1 => array(
"subscriber" => "apied.be",
"code" => 550,
"status" => 51),
2 => array(
"subscriber" => "beton-dobbelaere.be",
"code" => 550,
"status" => 50),
3 => array(
"subscriber" => "live.be",
"code" => 550,
"status" => 51),
4 => array(
"subscriber" => "hotmail.be",
"code" => 550,
"status" => 51),
5 => array(
"subscriber" => "telenet.be",
"code" => 550,
"status" => 50),
6 => array(
"subscriber" => "telenet.be",
"code" => 550,
"status" => 55),
7 => array(
"subscriber" => "telenet.be",
"code" => 550,
"status" => 51),
8 => array(
"subscriber" => "telenet.be",
"code" => 550,
"status" => 51)
);
/**
*@param array $counted The array already counted or NULL
*@param array $new The array to count or to merge with the counted $counted
*/
function merge_xor_count(array $counted = NULL, array $new){
if($counted === NULL){
$counted = array();
}
foreach($new as $keyNew => $valueNew){
$matches = false;
foreach($counted as $keyOut => $valueOut){
if ($valueOut['subscriber'] == $valueNew['subscriber'] && $valueOut['code'] == $valueNew['code'] &&
$valueOut['status'] == $valueNew['status']){
$matches = $keyOut;
}
}
if($matches !== false){
$counted[$matches]['amount']++;
}
else{
if(!isset($valueNew['amount'])) $valueNew['amount'] = 1;
$counted[] = $valueNew;
}
}
return $counted;
}
$output = merge_xor_count(NULL, $input);
print_r ($output)."\n";
$output = merge_xor_count($output, $input);
print_r ($output)."\n";
?>
Я не уверен, насколько эффективен этот код с действительно большим количеством элементов (BTW, вы не указали порядок величины чисел), но я думаю, что это будет более эффективно, чем преобразование массивов в коллекции Laravel
$arr = [
0 => [
"subscriber" => "gmail.com.",
"code" => 554,
"status" => 50,
],
1 => [
"subscriber" => "apied.be",
"code" => 550,
"status" => 51,
],
2 => [
"subscriber" => "beton-dobbelaere.be",
"code" => 550,
"status" => 50,
],
3 => [
"subscriber" => "live.be",
"code" => 550,
"status" => 51,
],
4 => [
"subscriber" => "hotmail.be",
"code" => 550,
"status" => 51,
],
5 => [
"subscriber" => "telenet.be",
"code" => 550,
"status" => 50,
],
6 => [
"subscriber" => "telenet.be",
"code" => 550,
"status" => 55,
],
7 => [
"subscriber" => "telenet.be",
"code" => 550,
"status" => 51,
],
8 => [
"subscriber" => "telenet.be",
"code" => 550,
"status" => 51,
],
];
$res = [];
foreach($arr as $element) {
if(empty($res[$element['subscriber']])) {
$res[$element['subscriber']] = [$element, 'count' => 1];
} else {
$res[$element['subscriber']]['count']++;
}
}
var_dump($res);
array_count_values()
?