Если элемент существует в списке, игнорируйте другие подобные элементы в С#

У меня есть список строк, сгенерированный программно следующим образом:

var list = new List<string>
{
    "anonim",
    "anonim şirket",
    "anonim şirketler",
    "tapu",
    "tapu senedi",
    "tapu kütüğü",
    "yaptırım",
    "müeyyide",
    "işçi",
    "işçi alacakları",
    "işçi hakları",
    "işçi lehine yorum ilkesi",
    "işçilik sözleşmesi",
    "limited şirket",
    "sınırlı ayni hak",
    "telif hakkı",
    "unutulma hakkı",
    "yolsuz tescil",
    "zamanaşımı"
};

Он содержит множество повторяющихся однородных элементов. Поэтому я подумал, что проигнорирую это с помощью словаря. Если в списке существует ключ словаря, я хочу игнорировать элементы, разделенные запятыми, в значении словаря. Вот словарь:

var dict = new Dictionary<string, string>
{
    {"anonim şirket", "anonim, anonim şirketler"}, 
    {"tapu senedi", "tapu, tapu kütüğü"}, 
    {"yaptırım", "müeyyide"}, 
    {"işçi hakları", "işçi, işçi alacakları, işçi lehine yorum ilkesi, işçilik sözleşmesi"}
};

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

var new_list = new List<string>()
{
    "anonim şirket",
    "tapu senedi",
    "yaptırım",
    "işçi hakları",
    "limited şirket",
    "sınırlı ayni hak",
    "telif hakkı",
    "unutulma hakkı",
    "yolsuz tescil",
    "zamanaşımı"
};

Я не знаю, как это сделать. Я думал написать цикл foreach, как показано ниже. Но я не знаю, что писать в цикле foreach.

var newList = new List<string>();
foreach (var l in list)
{
    // WHAT MUST I DO IN HERE?
}

Здесь вам нужно лучше определить свое намерение. Например, почему {"tapu senedi", "tapu, tapu kütüğü"}, а не {"tapu", "tapu senedi"} — оба у вас в первом списке. Откуда вы берете эти значения и т. д. Каков порог отклонения значения и т. д.?

T.S. 11.06.2024 22:11

@Т.С. - Эти значения представлены в виде списка. Список также взят из базы данных. Так как я работал над списком, то не хотел беспокоить вас, мастера, базой данных. Что касается того, почему некоторые предметы... Я по профессии юрист. Программное обеспечение — это хобби, которое значительно облегчает мою работу. Таким образом, более юридически правильными являются те, которые я дал в словарном ключе.

Johnny Wind 11.06.2024 22:16

Хранение дубликатов в виде строк, разделенных запятыми, в Dictionary<string, string> не будет ни красивым, ни эффективным. Вместо того, чтобы представлять нам свою попытку решения проблемы и просить нас исправить ваше решение, предпочтительнее описать проблему как можно лучше и позволить нам предложить решение. Скорее всего, таким образом вы получите лучшую помощь.

Theodor Zoulias 11.06.2024 22:28

Допустим, список содержит значения "anonim" и "anonim şirketler" и не содержит значения "anonim şirket". Что должно произойти в таком случае? Следует ли удалить одно из двух похожих значений или оба должны остаться в списке? Если один из них следует удалить, то какой?

Theodor Zoulias 11.06.2024 22:34

@TheodorZoulias - Я ценю, что ты пытаешься мне помочь. Но список действительно похож на тот пример, который я привел. Итак, список содержит как anonim, anonim şirket и anonim şirketler.

Johnny Wind 11.06.2024 22:48

Кстати, не обижайтесь на предпочитаемый вами алфавит, но здесь больше шансов получить помощь, если ваш пример набора данных состоит из английских слов. Большинство людей здесь лучше знакомы с английским языком и латинским алфавитом, и им будет легче визуально отличить похожие строки от несходственных. Чем проще вы поможете нам вам помочь, тем больше вероятность, что вам помогут.

Theodor Zoulias 11.06.2024 22:53

Если входные и выходные данные программы статичны, не пишите программу. Если входные данные могут измениться, вы сможете объяснить ожидаемое поведение для другого набора данных. Вопрос: с list и dict, что является динамическим вводом, что является статическими вспомогательными данными и/или промежуточными результатами (обработанными на основе ввода)?

grek40 11.06.2024 22:58

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

Theodor Zoulias 11.06.2024 23:01

Для вас софт – хобби, для нас – серьезный бизнес. Вы должны помочь нам понять вашу проблему, ваш вклад, результаты и критерии. Даже ИИ не сможет решить ее без единого алгоритма. например, ИИ может найти на изображении с камеры белый квадрат и т. д. Ни один из ваших комментариев не помог нам приблизиться к предложению. Например, если у вас есть "anonim", "anonim şirket", "anonim şirketler", - как вы решаете, что оставить, а что продублировать и выбросить?

T.S. 12.06.2024 03:26

@TheodorZoulias Разве не было ясно, что если список содержит ключ в словаре, элементы в значении этого ключа следует удалить? Вот как я это понял, и что показывают ожидаемые результаты.

Rufus L 13.06.2024 05:53

@Т.С. Он уточнил, что если ключ присутствует в списке, элементы связанного значения должны быть удалены из списка. Это очень простой алгоритм.

Rufus L 13.06.2024 05:54

@RufusL да, это совершенно ясно. Это не настолько общая проблема, чтобы ее стоило решать, поскольку список уже известен. ОП не может указать, каким должен быть результат для немного другого ввода, что весьма разочаровывает. Лично я хотел бы попытаться решить более общую проблему, но не эту.

Theodor Zoulias 13.06.2024 08:25

@RufusL «если список содержит ключ в словаре, элементы в значении этого ключа должны быть удалены» - я бы предложил включить это уточнение в вопрос (если вы на 100% уверены, что оно описывает алгоритм, который ОП хочет реализовать).

Theodor Zoulias 13.06.2024 08:35

@TheodorZoulias Он включил это в вопрос: «Если ключ словаря существует в списке, я хочу игнорировать элементы, разделенные запятыми в значении словаря».

Rufus L 13.06.2024 08:41

@RufusL ах, да, ты прав.

Theodor Zoulias 13.06.2024 08:43
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
15
105
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Простой способ сделать это (но не самый эффективный):

  1. сделать копию исходного списка
  2. перебрать ключи словаря
  3. если ключ существует в новом списке, удалите элементы, указанные в значении, из нового списка.

Мы можем разделить значение на запятую, чтобы создать мини-список для перебора для удаления элементов (обратите внимание, что было бы проще, если бы вместо этого вы использовали Dictionary<string, List<string>>):

// Make a copy of the original list
var new_list = list.ToList();

// Loop through the dictionary
foreach (var item in dict)
{
    // If our new list contains a key
    if (new_list.Contains(item.Key))
    {
        // Loop through the values associated with 
        // that key and remove them from the list
        foreach(var value in item.Value.Split(',').Select(i => i.Trim()))
        {
            new_list.Remove(value);
        }
    }
}

// Display results
Console.WriteLine(string.Join("\n", new_list));


Обновлено: Более эффективным способом, вероятно, было бы сначала создать список элементов, которые нужно исключить, путем поиска ключей словаря в списке, как мы делали раньше, но собирая все значения в отдельный список, а затем мы можем использовать метод Except для удалите элементы (что дает дополнительное преимущество [для некоторых] в одной строке):

var new_list = list.Except(dict
    .Where(item => list.Contains(item.Key))
    .SelectMany(item => item.Value.Split(',').Select(i => i.Trim())))
    .ToList(); // Call ToList() if you need a List and not just an IEnumerable

Здесь у вас есть алгоритм O(n³). List<T>.Remove — это O(n), и вы вызываете его во внутреннем цикле.

Theodor Zoulias 13.06.2024 08:31

@TheodorZoulias Да, я сразу сказал, что это неэффективно. Просто даю отправную точку для размышлений об этом.

Rufus L 13.06.2024 08:36

Руфус, текст в вашем ответе создает впечатление, что медленная часть - это «сделать копию исходного списка», а не то, что следует дальше.

Theodor Zoulias 13.06.2024 08:38

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

Theodor Zoulias 13.06.2024 08:57

@TheodorZoulias правда. я добавил более эффективный метод для этого, но думаю, что исходного ответа было достаточно для вопроса. взгляд на сам дизайн заставляет меня поверить, что это не наименее эффективный фрагмент кода. :)

Rufus L 13.06.2024 09:34

Я скептически отношусь к тому, что подход LINQ является улучшением (в отношении производительности). Он не использует преимущества того, что dict является словарем.

Theodor Zoulias 13.06.2024 09:38

@TheodorZoulias, дайте мне знать, если придумаете что-нибудь получше!

Rufus L 13.06.2024 10:16

Скорее всего, не буду. Я не считаю этот вопрос достаточно интригующим/сложным/интересным.

Theodor Zoulias 13.06.2024 10:26

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