2013-09-06 4 views
7

У меня есть 2 списка объект типа некоторого класса,Как использовать локальные переменные в лямбда-выражения

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

List<person> pr = new List<person>(); 
pr.Add(new person { id = "2", name = "rezoan" }); 
pr.Add(new person { id = "5", name = "marman" }); 
pr.Add(new person { id = "3", name = "prithibi" }); 

List<person> tem = new List<person>(); 
tem.Add(new person { id = "1", name = "rezoan" }); 
tem.Add(new person { id = "2", name = "marman" }); 
tem.Add(new person { id = "1", name = "reja" }); 
tem.Add(new person { id = "3", name = "prithibi" }); 
tem.Add(new person { id = "3", name = "prithibi" }); 

Теперь я должен получить все идентификаторы из «пр» ListObject, что не имеет никаких записей или нечетное количество записей в "tem" ListObejct. используя лам.

Для этого я использовал,

HashSet<string> inconsistantIDs = new HashSet<string>(pr.Select(p => p.id).Where(p => tem.FindAll(t => t.id == p).Count == 0 || tem.FindAll(t => t.id == p).Count % 2 != 0)); 

и она отлично работает.

но вы можете видеть из кода я использовал tem.FindAll (т => t.id == р) .Count дважды comapre с == 0 и % 2! = 0.

Есть ли способ использовать tem.FindAll (т => t.id == р) .Count раз и сохранить его во временную переменную, а затем сравнить эту переменную с == 0 и % 2! = 0.

Проще говоря, я просто хочу использовать его один раз для двух условий здесь.

+0

Пожалуйста, не используйте subjjects как «лицом выпуска в xxx ", это будет ссылка google. –

+0

Got u @TimSchmelter – Rezoan

ответ

14

Use a statement lambda instead of an expression lambda

var inconsistantIDs = new HashSet<string>(
      pr.Select(p => p.id).Where(p => 
        { 
        var count = tem.FindAll(t => t.id == p).Count; 
        return count == 0 || count % 2 != 0; 
        } 
      )); 
+0

Ya это работает. но «count .Count% 2! = 0» должно быть «count% 2! = 0». не могли бы вы просто исправить это. @Ahmed KRAIEM – Rezoan

+3

Вместо 'FindAll' я бы использовал' Count() '. Первый должен создать новую коллекцию для каждого человека. –

+0

@Rezoan Исправлено. @Tim Это правда. 'var count = tem.Count (t => t.id == p);' –

2
HashSet<string> inconsistantIDs = new HashSet<string>(
    pr.Select(p => new { Id = p.id, Cnt = tem.FindAll(t => t.id == p.id).Count() }) 
     .Where(p => p.Cnt == 0 || p.Cnt % 2 != 0) 
     .Select(p => p.Id); 
+0

Спасибо, но это дало мне ошибку на «t.id == p» и «.Count()» должно быть «.Count». не могли бы вы увидеть эту проблему. – Rezoan

+0

Исправлено. Но я бы не использовал этот код, если вы его не понимаете. –

4

Возможно просто:

var query = pr.Where(p => { int c = tem.Count(p2 => p.id == p2.id); return c == 0 || c % 2 != 0; }); 

возвращает два человека:

2 "rezoan" 
5 "marman" 
2

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

Прямо сейчас у вас есть O(n*m) алгоритм, который будет сокращен до O(n+m):

// create a map (id -> count), O(m) operation 
var dictionary = new Dictionary<string, int>(); 
foreach (var p in tem) 
{ 
    var counter = 0; 
    dictionary.TryGetValue(p.id, out counter); 
    counter++; 
    dictionary[p.id] = counter; 
} 

// search the map, O(n) operation 
var results = new HashSet<string>(); 
foreach (var p in pr) 
{ 
    var counter = 0; 
    dictionary.TryGetValue(p.id, out counter); 
    if (counter == 0 || counter % 2 != 0) 
     results.Add(p.id); 
} 
+0

Спасибо за вашу ценную информацию.+1 @Groo – Rezoan

3

Кроме заявления лямбда можно использовать let clause:

HashSet<string> inconsistantIDs = new HashSet<string>(
    from p in pr 
    let count = tem.FindAll(t => t.id == p).Count 
    where count == 0 || count % 2 != 0 
    select p.id 
); 
Смежные вопросы