Проверка на повторяющиеся значения

Я создаю форму с помощью цикла, выводящего значения внутри некоторых текстовых полей. Мне нужно проверить, есть ли повторяющиеся значения. Я думаю, мне нужно также поместить значения в массив и проверять их на каждом выходе.

$duplicates = array();
$has_duplicate = false;

foreach ($vals AS $v) {

   if (in_array($v->val, $duplicates)) {
      $has_duplicate = true;
   }

   echo '<input type = "text" value = "'.$v->val.'" class = "'.($has_duplicate ? 'dupe' : '').'">';

   $duplicates[$v->val] = true;       
}

Что-то вроде этого?

Откуда берутся данные, возможно, лучше исправить дублирование до того, как оно произойдет. ЕСЛИ это невозможно, вы можете использовать комбинацию array_column и array_count_values (или array_column, и array_unique, array_diff), но мне нужно, чтобы указанный массив был более полезным.

ArtisticPhoenix 25.10.2018 23:52

Вы можете использовать count(array_unique(array_column($vals, 'val'))). Если это то же самое, что и count($vals), то дубликатов нет.

Barmar 25.10.2018 23:56

Какой у Вас вопрос?

RiggsFolly 25.10.2018 23:56

Да что-то подобное. И собственно сам код.

revo 25.10.2018 23:56

Если вы собираетесь сделать это таким образом, вы должны установить цикл $has_duplicate = false;внутри. В противном случае он сохранит свое значение true из предыдущей итерации.

Don't Panic 25.10.2018 23:58

Обратите внимание, что эта форма array_column будет работать только в PHP 7. В PHP 5 она может использоваться только для массивов массивов, но не для массивов объектов.

Barmar 25.10.2018 23:58

@ Don'tPanic Если найден дубликат, дубликаты всегда есть.

Barmar 25.10.2018 23:58

@Barmar он пометит следующее значение в $vals как $has_duplicate, даже если у этого значения нет дубликата. Переключатель $has_duplicate никогда не выключается.

Don't Panic 26.10.2018 00:00

ОП поднимает флаг. Не обращайте внимания на имена переменных. Все значения должны иметь соответствующий key в $duplicates. Даже ответ ниже неверен. Код хорошо работает для OP.

revo 26.10.2018 00:02

Я имею в виду, что $has_duplicate выглядит не так, как будто он должен применяться ко всему набору, а к конкретному значению, поскольку он определяет класс на входе для этого значения.

Don't Panic 26.10.2018 00:03

@ Don'tPanic Я не заметил, что он использовал переменную в операторе echo, я подумал, что это просто глобальный флаг, сообщающий, были ли найдены какие-либо дубликаты.

Barmar 26.10.2018 00:06
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
11
54
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Собственно проблему вижу:

foreach ($vals AS $v) {
   if (in_array($v->val, $duplicates)) {
      $has_duplicate = true;
   }

$duplicates[$v->val] = true;

Вам нужно проверить isset например:

foreach ($vals AS $v) {
    $has_duplicate = false; //reset on each iteration of the loop
    if (isset($duplicates[$v->val])) {
         $has_duplicate = true;
    }
....

Проблема в том, что in_array смотрит в values, и вы устанавливаете все значения на true, вам нужно проверить ключи ($duplicates[$v->val] = true;), в которые вы помещаете свои данные.

Вы также можете использовать array_key_exists() для проверки, но этим никто не пользуется, так как он медленнее, чем isset.

in_array — Checks if a value exists in an array

bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )

http://php.net/manual/en/function.in-array.php

То, что я делал больше раз, чем хочу признаться.

ОБНОВИТЬ

Лучший способ написать это - просто покончить с локальной переменной, поскольку она на самом деле не нужна (если нет других мест, где она используется, не включенных в вопрос)

foreach ($vals AS $v) {
  echo '<input type = "text" value = "'.$v->val.'" class = "'.(isset($duplicates[$v->val]) ? 'dupe' : '').'">';
  $duplicates[$v->val] = true;       
}

На самом деле нет никакой разницы, если вы установите это $duplicates[$v->val] = true; несколько раз как True is True.

Ваше здоровье!

Как упоминалось в комментариях, вам нужно сбрасывать $has_duplicate каждый раз в цикле, а не сохранять его значение с предыдущей итерации. Итак, вы можете просто сделать:

$has_duplicate = isset($duplicates[$v->val]);
Ответ принят как подходящий

Я думаю, если вы хотите пометить все значения, у которых есть дубликаты, вам нужно дважды повторить $vals. В противном случае первый экземпляр значения, который появляется несколько раз, не будет помечен как дубликат, потому что нельзя определить, что он дублирован, пока это значение не встретится снова.

foreach ($vals as $v) {
    if (isset($unique[$v->val])) $duplicates[$v->val] = true;
    $unique[$v->val] = true;
}

foreach ($vals as $v) {
    $class = isset($duplicate[$v->val]) ? 'dupe' : '';
    echo '<input type = "text" value = "'. $v->val .'" class = "'. $class .'">';
}

Если вы хотите пометить только последующие экземпляры значения с помощью класса dupe, один цикл будет делать

foreach ($vals as $v) {
    $class = isset($unique[$v->val]) ? 'dupe' : '';
    echo '<input type = "text" value = "'.$v->val.'" class = "'. $class .'">' . "\n";
    $unique[$v->val] = true;
}

Это хороший момент (я немного торопился ... лол ... уходил с работы примерно через 10 минут)

ArtisticPhoenix 26.10.2018 00:16

@ArtisticPhoenix ну, я не уверен, что это то, что нужно. Но я думаю, что для людей, которые найдут эти вопросы и ответы позже, все может пойти по другому пути.

Don't Panic 26.10.2018 00:22

Другие вопросы по теме