Удалить все дубликаты данных из многомерного массива

Примечание. Ответ @Matthews правильный, но если вы находитесь в другом потоке, и вы вызываете вызов волейбола, когда у вас нет интернета, ваш обратный вызов будет вызываться в основном потоке, но поток, на котором вы находитесь, будет заблокирован FOREVER. (Поэтому, если этот поток является IntentService, вы никогда не сможете отправить ему другое сообщение, и ваша служба будет в основном мертвой).

Используйте версию get() с таймаутом future.get(30, TimeUnit.SECONDS) и поймать ошибку, чтобы выйти из вашего потока.

Чтобы ответить на ответ @Mathews:

        try {
            return future.get(30, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            // exception handling
        } catch (ExecutionException e) {
            // exception handling
        } catch (TimeoutException e) {
            // exception handling
        }

Ниже я завернул его в метод & amp; используйте другой запрос:

   /**
     * Runs a blocking Volley request
     *
     * @param method        get/put/post etc
     * @param url           endpoint
     * @param errorListener handles errors
     * @return the input stream result or exception: NOTE returns null once the onErrorResponse listener has been called
     */
    public InputStream runInputStreamRequest(int method, String url, Response.ErrorListener errorListener) {
        RequestFuture<InputStream> future = RequestFuture.newFuture();
        InputStreamRequest request = new InputStreamRequest(method, url, future, errorListener);
        getQueue().add(request);
        try {
            return future.get(REQUEST_TIMEOUT, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Log.e("Retrieve cards api call interrupted.", e);
            errorListener.onErrorResponse(new VolleyError(e));
        } catch (ExecutionException e) {
            Log.e("Retrieve cards api call failed.", e);
            errorListener.onErrorResponse(new VolleyError(e));
        } catch (TimeoutException e) {
            Log.e("Retrieve cards api call timed out.", e);
            errorListener.onErrorResponse(new VolleyError(e));
        }
        return null;
    }
0
задан mickmackusa 16 January 2019 в 05:40
поделиться

2 ответа

Это не сохраняет первоначальный порядок ввода, но потому что данные проиндексированы, поэтому я предполагаю, что это не имеет значения.

Имея всего 3 вызова в одной строке, вы назначаете временные ассоциативные ключи сзади вперед, чтобы исключить последние дубликаты (поскольку php не разрешает дублирование ключей), а затем при желании удаляете временные ключи с помощью array_values(). Нет повторных вызовов функций. Нет массивов поиска.

Код: ( Демонстрация )

$array = [
    ['id_card' => 11883834, 'type' => 1, 'registed' => 1547610891],
    ['id_card' => 20311077, 'type' => 1, 'registed' => 1547610891],
    ['id_card' => 16187903, 'type' => 3, 'registed' => 1547610891],
    ['id_card' => 16354099, 'type' => 1, 'registed' => 1547610891],
    ['id_card' => 21133393, 'type' => 4, 'registed' => 1547610891],
    ['id_card' => 15452852, 'type' => 2, 'registed' => 1547610891],
    ['id_card' => 19775869, 'type' => 2, 'registed' => 1547610891],
    ['id_card' => 20311077, 'type' => 1, 'registed' => 1547610891],
    ['id_card' => 21133393, 'type' => 4, 'registed' => 1547610891],
    ['id_card' => 11883834, 'type' => 1, 'registed' => 1547610891]
];

var_export(array_values(array_column(array_reverse($array), null, 'id_card')));

Если вы передумаете желать сохранить первое вхождение, вы можете удалить array_reverse(). Если клавиши первого уровня не имеют значения на выходе, вы можете удалить array_values(). Эти изменения позволили бы решить проблему как вызов одной функции.

p.s. "REGIST эр ред"

0
ответ дан mickmackusa 16 January 2019 в 05:40
поделиться

Таким образом, проблема заключается в том, что решения array_unique ожидают, что все значение будет эквивалентным - они не просто сравниваются на основе вашего поля идентификатора.

Вместо этого вы, вероятно, захотите пройтись по массиву и отследить, какие идентификаторы вы видели, и взять только те элементы, для которых вы раньше не видели идентификатор.

function filter_duplicate_id_cards($data) {
  $seen = array(); // To keep track of the IDs we've seen
  $filtered = array(); // Will hold the result

  foreach($data as $item) {
    if(array_key_exists($item['id_card'], $seen)) {
      // We already encountered this id card before.
      continue;
    }

    // Never-before seen id card, append it to the result and set the key in $seen
    $filtered[] = $item;
    $seen[$item['id_card']] = TRUE;
  }

  return $filtered;
}

Обратите внимание, что здесь используется форма карты массива PHP, а не просто добавление видимых идентификаторов в форму списка и использование чего-то вроде in_array для проверки, видели ли мы ключ. Это важно с точки зрения производительности, особенно если мы собираемся работать с большими наборами данных - in_array - это O (n) с количеством элементов в массиве, тогда как array_key_exists - это O (1).

Более общая версия этой функции будет выглядеть следующим образом:

function filter_duplicate_field($data, $field) {
  $seen = array(); // To keep track of the keys we've seen
  $filtered = array(); // Will hold the result

  foreach($data as $item) {
    if(array_key_exists($item[$field], $seen)) {
      // We already encountered this key before.
      continue;
    }

    // Never-before seen key, append it to the result and set the key in $seen
    $filtered[] = $item;
    $seen[$item[$field]] = TRUE;
  }

  return $filtered;
}

Вы можете затем назвать ее как $result = filter_duplicate_field($data, 'id_card');.

0
ответ дан Amber 16 January 2019 в 05:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: