Удалить объект на основе некоторого условия

#c# #.net #linq

#c# #.net #linq

Вопрос:

 public class Name    {
    public string language { get; set; } 
    public string text { get; set; } 
}

public class ValueItem    {
    public string id { get; set; } 
    public List<Name> names { get; set; } 
    public object syn { get; set; } 
    public List<string> prop { get; set; } 
    public string dataType { get; set; } 
}

public class Source    {
    public string id { get; set; } 
    public string name { get; set; } 
}

public class Result    {
    public List<ValueItem> valueItems { get; set; } 
    public Source source { get; set; } 
}

public class Data    {
    public List<Result> result { get; set; } 
    public int totalpages { get; set; } 
    public int totalrecords { get; set; } 
    public int pagesize { get; set; } 
    public int pagenumber { get; set; } 
}
  

у меня есть структура модели, подобная приведенной выше, я пытаюсь удалить объект с именем на основе текста. Если строка, которую я передаю, присутствует в Name.text, этот конкретный объект name должен быть удален. Как добиться этого с помощью linq или lambda.
я пытался : var data1= data.Result.Where(x=>x.ValueItems.Where(a=>a.Names.SelectMany(b=>!str.Contains(b.Text)))).ToList()

Комментарии:

1. Попробуйте это (я думаю, это должно сработать): var data1= data.Result.Where(x=>x.ValueItems.Where(a=>a.Names.Any(b=>b.Text.Contains(str)))).ToList(); . Вы сказали, что если текст содержит строку, а не наоборот, что вы и делаете. Отрицание также не соответствует тому, что вы говорите, что хотите в результате.

2. Просто чтобы убедиться: 1) Запрос linq не удалит никаких объектов, он вернет новый список с отфильтрованными результатами и 2) Если пробелы неуместны, вы можете захотеть обрезать входную строку перед использованием ее в запросе.

3. Если условие соответствует, следует ли удалять весь result объект или только name ? используемый вами linq фильтрует result объект, а не names . Не могли бы вы, пожалуйста, привести какой-нибудь пример?

Ответ №1:

Вы можете добиться желаемого, вернув отфильтрованную версию исходных данных:

 data.result = data.result.Select(x => new Result
{
    source = x.source,
    valueItems = x.valueItems.Select(a =>
                                         new ValueItem
                                         {
                                             prop = a.prop,
                                             dataType = a.dataType,
                                             id = a.id,
                                             syn = a.syn,
                                             names = a.names
                                                     .Where(i => i.text != stringToRemove)
                                                            .ToList()
                                         }).ToList()

}).ToList();
  

Однако альтернативной версией (без использования LINQ) достижения того же самого может быть:

 foreach (var result in data.result)
{
    foreach (var resultValueItem in result.valueItems)
    {
        resultValueItem.names.RemoveAll(i => i.text == stringToRemove);
    }
}
  

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


Несколько замечаний к вышеупомянутым решениям:

  1. Если вам не нужно точное совпадение, но возможны сценарии, когда ваш текст может быть частью строки большего размера, используйте String.Содержит вместо приведенного выше сравнения.
  2. Рассмотрите возможность применения одной из строк: .Уменьшить, строку.ToLowerInvariant, String.Обработчик, String.Жестковариантные методы для обоих stringToRemove и i.text на случай, если вы хотите сравнение без учета регистра.