2013-06-27 4 views
3

(Я сделал максимально возможный поиск на основе ключевых слов «removeall where» или «removeall two argument predicate» без большой удачи, поэтому здесь идет)C# List removeall принимает два аргумента в предикате?

Проблема У меня есть список объектов (класса Wave) и функцию отношения как: частный bool AinB (Wave A, Wave B), возвращающий true, если A 'находится в B. Также AinB (x, y) является истинным, гарантируя, что AinB (y, x) является ложным ,

Каков наилучший способ удалить все объекты в списке, где объекты находятся в «другом объекте в списке? то есть после удаления список должен содержать только объекты, где ни один из них не находится в отношении «находится в» с каким-либо другим объектом в списке?

в идеале это может быть сделано легко, как

listX.RemoveAll ((х, у) => AINB (х, у)), но, конечно, это не является законным в C#, также нет простого способа укажите, для удаления, x или y.

Я думал о пробегает по списку с индексом

int i = listX.Count - 1; 
while (i>=0) 
{ 
    int r = listX.RemoveAll(X => AinB(X, listX[i])); 
    i = i - r - 1; 
} 

Это, кажется, работает, но мне интересно, если есть лучший способ с прямым кодом Linq, чтобы решить эту проблему. Спасибо.

+0

От звуков его, вы будете строить дерево, это правильно? Я делаю предположение в своем ответе, что AinB изучает узлы дерева и определяет, является ли 'A' дочерним элементом' B'. – Mgetz

+0

Нет, это довольно сложно, и этот «фильтр» является лишь одним из «отношений», но доминирующим для фильтрации большинства объектов. –

ответ

7

К сожалению, я не могу придумать, как это сделать, это не по крайней мере O (n^2). Но хорошая новость заключается в том, что это не так сложно с точки зрения LINQ:

listX.RemoveAll(item => listX.Any(isin => AinB(item, isin))); 
+0

Это похоже на то, что я ищу.Предположим, что listX обладает свойством сортировки, когда элементы в конце имеют более высокую вероятность «включения» элементов на фронтах, как заставить оценку быть от конца до начала списка, как в моем исходном цикле. –

+0

С этими функциями вы не можете. Вы можете попробовать «Реверс», но это не гарантирует, что «removeall» посетит что-нибудь в любом порядке. – quetzalcoatl

-2

вы можете использовать LINQ Кроме вызова

List a = new List(); 
a.Add("a"); 
a.Add("b"); 
a.Add("c"); 
List b = new List(); 
b.Add("b"); 
b.Add("c"); 
b.Add("d"); 
List c = a.Except(b); 

список с будет содержать только пункт «а»;

вы можете даже сделать его более умным, давая сравнить объект,

List c = a.Except(b, new CompareObject()); 
+0

Думаю, вам нужно более внимательно пересмотреть вопрос. Речь идет не только о разнице в настройках. – quetzalcoatl

+0

@quetzalcoatl, тогда что это? – Jegan

+0

Это также не _just about_ set difference, потому что другой набор еще неизвестен и должен быть определен. Если вы хотите ответить, объясните, как подготовить Comparer, чтобы он выполнял требуемые проверки. В настоящее время у вас есть только 50% ответа. Я не вызываю код, просто короткое объяснение. – quetzalcoatl

0

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

Пример:

List<string> stuff = new List<string>(); //full of stuff 
for(int i = stuff.Count - 1; i > 0; i--) 
{ 
    //Edited here for more efficiency. 
    for (int x = i - 1; x > 0; x--) 
    { 
     if (stuff[x] == stuff[i]) 
     { 
      stuff.RemoveAt(i); 
      break; //or possibly continue; 
     } 
    } 
} 

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

Если вы мастер с помощью LINQ вы можете попробовать сгруппировать объекты в списке, а затем просто выбрать первый объект в каждой группе для вашего списка выходного ..

+1

Кому-то, вероятно, не понравилось/i/x .. В наши дни люди не любят императивный способ – quetzalcoatl

+0

Я уверен, что LINQ (намного) медленнее, чем двойной. Люди полагаются слишком много на один лайнер в C#. – Izzy

+0

Правильно ли это? Как только удаление будет выполнено, размер списка будет уменьшен, и вы по-прежнему будете циклически основываться на исходном индексе? –