Слияние дубликатов массивов с количеством

1

Я работаю с большими наборами данных, и мне нужно объединить массивы, когда они дублируются. Если они объединяются, мне нужен счет, добавленный в массив.

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, если необходимо, я могу превратить массив в коллекцию, поэтому доступны вспомогательные функции

  • 0
    интересный вопрос. вы пробовали array_count_values() ?
  • 0
    В настоящее время вы собираете эти наборы данных из чего-то вроде MySql?
Показать ещё 3 комментария
Теги:
arrays
laravel-5.1
array-merge

3 ответа

0
Лучший ответ

Мне удалось исправить это с помощью цикла 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 уже существует до запуска этого цикла, вместо того, чтобы добавлять его во время этого цикла.

0

Пытаться

<?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";


    ?>
  • 0
    Это все еще выводит полный набор результатов? Все еще получите 3721 результатов, посмотрите на ответ, который я дал себе.
0

Я не уверен, насколько эффективен этот код с действительно большим количеством элементов (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);
  • 0
    Это все еще дает мне 3721 результат.
  • 0
    было бы трудно отлаживать, если у меня как-то не будет полного набора данных. Вы видите, как это работает на предоставленном вами образце?
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню