2015-08-14 2 views
3

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

List<data> dataList = somedata; 
IEnumerable<Filter> filterList = someFilterData; 

, а затем я делаю фильтрацию, используя этот код:

foreach (var s in filterList) 
{ 
    dataList = dataList .Where(l => l.dataId!= s.Id).ToList();  
} 

Может кто-то пожалуйста, предложить, если это достаточно хороший подход, или, как мы можем сделать его лучше использовать некоторые другой метод. Примечание. Список может стать большим, поэтому мы также думаем о производительности.

+0

я бы поставил Id фильтры внутри HashSet, а затем сделать один, где, проверяя, если dataId не внутри хэш – George

ответ

3

Что вам нужно взять только эти пункты, которые не могут быть найдены в список фильтров. Вы можете сделать это в «старой школы» способ, с помощью петель:

foreach (var listItem in dataList) 
{ 
    foreach (var filterItem in filterList) 
    { 
     if (listItem == filterItem) 
     { 
      dataList.Remove(listItem); 
      continue; 
     } 
    } 
} 

Или вы можете использовать LINQ, чтобы сделать фильтрацию:

dataList.Where(d => filterList.All(f => f.Id != d.dataId)) 
+1

Мне нравится ваше решение. Он дает правильные ответы и чист. Мое решение дает правильный ответ, но кажется неуклюжим. – AlwaysAProgrammer

+1

@Mogsdad Спасибо, что подняли проблему. Я прочитал ответы в теме из StackExchange, которые вы связали, и я согласен с тем, что там было сказано. Я буду расширять свой ответ сегодня или завтра. – Kapol

0

Возможно, вам это нужно

dataList = dataList.Where(l => !filterList.Select(x => x.Id).Contains(l.dataId)).ToList(); 
+0

filterList.Contains является неправильным здесь. filterList - это список фильтров, а не список идентификаторов или данных. – AlwaysAProgrammer

+0

@AlwaysAProgrammer Спасибо за комментарии об ошибке –

1

Я хотел бы сделать это, используя HashSet, а затем один Где:

var filtIds = new HashSet<int>(filterList.Select(f=> f.Id)); 
var filteredDataList = dataList.Where(d=> !filtIds.Contains(d.dataId)).ToArray(); 
+0

+1 Более эффективный подход. Но он хочет отфильтровать список, поэтому 'dataList = .... ToList()' более уместен. –

0
var filteredQuery = 
       from d in dataList 
       let filterListIds = from f in filterList 
        select f.Id 
       where filterListIds.Contains(d.DataId) == false 
       select d; 
+2

@Mogsdad ... Я не понимаю вашего комментария. Ответ, который принимается, также является кодом. Мое решение не является «попыткой» этого решения. Я действительно закодировал его, и он работает. – AlwaysAProgrammer

+0

@Mogsdad; Спасибо за объяснение. То, что вы говорите, имеет смысл. – AlwaysAProgrammer

1

Late к партии, но, так как ваш фильтр известен только как IEnumerable, может быть, не рекомендуется воссоединять фильтры, чтобы предотвратить сосание тогда из источника на каждой итерации? Я думаю, это то, что @George получает. Если источник фильтров изменилось в середине исполнения, это может быть непоследовательным (и, возможно, дорогостоящим для повторного получения их на каждой итерации):

var filterIds = filterList.Select(f=> f.Id).ToArray(); 

Затем «Не любой» только кажется (мне), чтобы сказать что вы имеете в виду больше, чем «Все не равные».

var results = dataList.Where(d=> !filterIds.Any(f=> d==f)); 
0

Таким образом, вы просто хотите удалить все из первого списка, отображаемого во втором списке, и производительность важна?

Мне нравится Georges approach больше всего, это самый эффективный, если список становится большим. Но List.RemoveAll также более эффективно:

dataList.RemoveAll(d => filterList.Any(x => x.ID == d.DataID)); 
Смежные вопросы