2012-01-30 2 views
1

Это, возможно, было рассмотрено, поэтому я заранее извиняюсь за это.LINQ GroupBy over

Во всяком случае, это мой несколько надуманный пример, я надеюсь, что он получает мой вопрос по:

Скажем, у нас есть эти классы

class WordExamples 
{ 
    public string word; 
    public List<Sentence> sentencesWithWord; 
    //constructor 
    public WordExamples(string word) { 
     this.word = word; 
    } 
} 

class Sentence 
{ 
    public List<string> words; 
} 

Затем мы создали два списка:

List<Sentence> sentences = GetSomeSentences(); 
List<WordExamples> wordExamples = 
    GetSomeWords().Select(w=>new WordExamples(w)); 

Как вы можете видеть, список WordExamples содержит примеры слов, которые неполны в том, что они не имеют предложений, созданных экземпляромWithWord.

Так что мне нужен аккуратный Linq, который установит это. То есть что-то вроде: foreach wordExample получить подмножество предложений, которые содержат слово и назначить его предложениямWordWord. (Withouth вложенными для петель, что есть)

редактировать: Добавление модификатора

+0

Как код может присваиваться 'sentencesWithWord', когда это личное поле, которое не используется в классе, который его объявляет? – svick

+0

@svick, да, это незащищенный псевдокод –

ответ

0

Как LINQ является запросом языка, не язык присваивания, вы должны использовать цикл:

List<WordExamples> wordExamples = GetSomeWords().Select(w=>new WordExamples(w)) 
               .ToList(); 


foreach(var wordExample in wordExamples) 
{ 
    wordExample.sentencesWithWord 
     = sentences.Where(x => x.words.Contains(wordExample.word)).ToList(); 
} 
+1

Этот код закрывает переменную цикла и не будет работать корректно. – Ani

+0

@Ani: Код компилируется и работает просто отлично. Вывод также ожидается. –

+0

@ DanielHilgarth, выход не ожидается. Все члены 'wordExamples' будут иметь' sentionsWithWord', установленные в соответствии с последним. – svick

2

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

foreach (var example in wordExamples) 
{ 
    Console.WriteLine("Word {0}", example.Key); 
    foreach (var sentence in example) 
    { 
     // I assume you've really got the full sentence here... 
     Console.WriteLine(" {0}", string.Join(" ", sentence.Words)); 
    } 
} 

EDIT: Если вы действительно необходимо WordExamples класс, вы могли бы:

public class WordExamples 
{ 
    public string Word { get; private set; } 
    public List<Sentence> SentencesWithWord { get; private set; } 

    public WordExamples(string word, List<Sentences> sentences) { 
     Word = word; 
     // TODO: Consider cloning instead 
     SentencesWithWord = sentences; 
    } 
} 

Это в основном так же, как элемент Lookup, заметьте ...

Во всяком случае, с этим на месте вы можете использовать:

var wordExamples = from sentence in sentences 
        from word in sentence.Words 
        group sentence by word into g 
        select new WordExample(g.Key, g.ToList()); 
+0

Жаль, что он недостаточно ясен. Я не следую вашему примеру ... WordExamples - это класс, ваш код, похоже, принимает по-другому. –

+0

@tycomiplex: Мой код не * использует * класс WordExamples, поскольку он, похоже, фактически не добавляет никакого значения, и вы все равно не предоставляли никакого способа получить его в списке. (То же самое относится и к Sentence и его члену слов, конечно ...) –

+0

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

0
IEnumerable<WordExamples> wordExamples = GetSomeWords().Select(w=> 
{ 
    var examples = new WordExamples(w); 
    examples.sentencesWithWord = sentences.Where(s => s.words.Any(sw => sw == w)).ToList(); 
    return examples; 
} 
); 

Не забудьте установить правильные модификаторы доступа.

0

Похоже, вы повторно изобретаете ILookup.

ILookup<string, Sentence> examples = GetSentences() 
    .SelectMany(sentence => sentence.words, (sentence, word) => new {sentence, word}) 
    .ToLookup(x => x.word, x => x.sentence); 
+0

Правильно, класс WordExamples работает как поиск, а не придумывает что-либо, просто пытается решить рабочий пример, где класс является сложным dto –