2

I suppose that this question might partially duplicate other similar questions, but i'm having troubles with such a situation:

I want to extract from some string sentences

For example from

`string sentence = "We can store these chars in separate variables. We can also test against other string characters.";`

I want to build an IEnumerable words;

var separators = new[] {',', ' ', '.'};

IEnumerable<string> words = sentence.Split(separators, StringSplitOptions.RemoveEmptyEntries);

After that, go throught all these words and take firs character into a distinct ascending ordered collection of characters.

var firstChars = words.Select(x => x.ToCharArray().First()).OrderBy(x => x).Distinct();

After that, go through both collections and for each character in firstChars get all items from words which has the first character equal with current character and create a Dictionary<char, IEnumerable<string>> dictionary.

I'm doing this way:

var dictionary = (from k in firstChars
                  from v in words
                  where v.ToCharArray().First().Equals(k)
                  select new { k, v })
                  .ToDictionary(x => x);

and here is the problem: An item with the same key has already been added. Whis is because into that dictionary It is going to add an existing character.

I included a GroupBy extension into my query

var dictionary = (from k in firstChars
                  from v in words
                  where v.ToCharArray().First().Equals(k)
                  select new { k, v })
                  .GroupBy(x => x)
                  .ToDictionary(x => x);

The solution above gives makes all OK, but it gives me other type than I need.

enter image description here What I should do to get as result an Dictionary<char, IEnumerable<string>>dictionary but not Dictionary<IGouping<'a,'a>> ?

The result which I want is as in the bellow image: enter image description here But here I have to iterate with 2 foreach(s) which will Show me wat i want... I cannot understand well how this happens ...

Any suggestion and advice will be welcome. Thank you.

mihai
  • 2,746
  • 3
  • 35
  • 56
  • Why would you write `x.ToCharArray().First()` instead of `x[0]`? And why would you use `Equals()` instead of `==`? – svick Jun 21 '13 at 14:46
  • @svic, this is a trivial decision `x.ToCharArray().First()` or `x[0]` :) `Equals()` instead of `==` also has a unimportant relevance. The big problem is that I need as result an `Dictionary>` . All responses redirect me from `Dictionary` to `ILookup`. I tried to make something according to boy's proposals, but it seems that i still encounter problems. I don't need to print result on console, but to send that dictionary to another receiver which requires `Dictionary>` at the input :) – mihai Jun 21 '13 at 14:54
  • One thing I realized: you're asking for the characters in ascending order in a `Dictionary`. Except that is not possible, `Dictionary` doesn't have any order on its keys. – svick Jun 21 '13 at 14:57
  • @svick, ok, they cannot be ordered, i'll be able to order them later into other context – mihai Jun 21 '13 at 14:59
  • And the first part of p.s.w.g.'s answer gives you a good way to do this using a `Dictionary`. – svick Jun 21 '13 at 14:59
  • @svick, right! I'm following his solution :) Thanks – mihai Jun 21 '13 at 15:02

2 Answers2

3

As the relation is one to many, you can use a lookup instead of a dictionary:

var lookup = words.ToLookup(word => word[0]);

loopkup['s'] -> store, separate... as an IEnumerable<string>

And if you want to display the key/values sorted by first char:

for (var sortedEntry in lookup.OrderBy(entry => entry.Key))
{
  Console.WriteLine(string.Format("First letter: {0}", sortedEntry.Key);
  foreach (string word in sortedEntry)
  {
    Console.WriteLine(word);
  }
}
vc 74
  • 37,131
  • 7
  • 73
  • 89
2

You can do this:

var words = ...
var dictionary = words.GroupBy(w => w[0])
                      .ToDictionary(g => g.Key, g => g.AsEnumerable());

But for matter, why not use an ILookup?

var lookup = words.ToLookup(w => w[0]);
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • I agree with first part of answer, thanks. The needed result is a Dictionary> but not an ILookup, because I'll send that dictionary to another receiver which requires Dictionary> at the input :) – mihai Jun 21 '13 at 15:03
  • 1
    @meorfi Fair enough. I think if your receiver doesn't *need* to add / remove items from the dictionary, it should probably be refactored to use the simpler interface, but whatever works :) -- happy coding. – p.s.w.g Jun 21 '13 at 15:05
  • I'll think about refactoring also. Thanks you for suggestion – mihai Jun 21 '13 at 15:08