none
[LINQ] GroupBy - to add one item at the end of current List RRS feed

  • Question

  • Hi my code goes like this;

    List<List<string>> myList =
    	new List<List<string>> {
    		new List<string> {"Quick", "a" },
    		new List<string> {"Brown", "b" },
    		new List<string> {"Fox", "c"},
    		new List<string> {"Fox", "d"},
    		new List<string> {"Fox", "e"},
    		new List<string> {"Jumps", "f" }
    	};
    var myResult = myList
    	.GroupBy(x => x[0])
    	.Select(y => new List<List<string>>
    	{
    		new List<string>{
    			string.Join(", ", y),
    			y.Count().ToString()
    		}
    	});
    MessageBox.Show(
    		string.Join("\n", myResult.Select( x => string.Join("\n", x.Select(z => string.Join(" ", z)))))
    		);

    My goal is like this (not the text itself but the "List"), the last number is frequency.

    //  Quick a 1
    //  Brown b 1
    //  Fox c 3
    //  Fox d 3
    //  Fox e 3
    //  Jumps f 1

    But, as you can see  my code is not so good. So current result is like this;

    //  System.Collections.Generic.List`1[System.String] 1
    //  System.Collections.Generic.List`1[System.String] 1
    //  System.Collections.Generic.List`1[System.String], System.Collections.Generic.List`1[System.String], System.Collections.Generic.List`1[System.String] 3
    //  System.Collections.Generic.List`1[System.String] 1

    What do I have to do ?

    Thanks






    Thursday, December 27, 2018 11:13 AM

Answers

  • Try this:

    var myResult2 = myList
        .GroupBy( x => x[0] )
        .Select( g => new { Name = g.Key, Letters = g.Select( i => i[1] ) } ).ToList();
    
    MessageBox.Show( string.Join( "\n", myResult2.SelectMany( z => z.Letters.Select( i => $"{z.Name} {i} {z.Letters.Count()}" ) ) ) );
    

    Thursday, December 27, 2018 1:31 PM

All replies

  • You can create a List<T> of Tuple and then do the following to get the character count in each word:

    List<Tuple<string, char>> items = new List<Tuple<string, char>>()
    {
            Tuple.Create("Quick", 'a'), 
            Tuple.Create("Brown", 'b'), 
    	Tuple.Create("Fox", 'c'), 
    	Tuple.Create("Fox", 'd'), 
    	Tuple.Create("Fox", 'e'), 
    	Tuple.Create("Jumps", 'f')
    };
    
    var resultant = items.Select(item => new
    {
    	Item = item, 
    	Count = item.Item1.Where(x => char.ToUpperInvariant(x) == char.ToUpperInvariant(item.Item2)).Count()
    });
    
    foreach (var item in resultant)
    {
          Console.WriteLine(String.Format("{0},{1},{2}", item.Item.Item1, item.Item.Item2, item.Count));
    }

    See the working DEMO Fiddle


    [If a post helps to resolve your issue, please click the "Mark as Answer" of that post or click Answered"Vote as helpful" button of that post. By marking a post as Answered or Helpful, you help others find the answer faster. ]


    Blog | LinkedIn | Stack Overflow | Facebook
    profile for Ehsan Sajjad on Stack Exchange, a network of free, community-driven Q&A sites


    • Edited by Ehsan Sajjad Thursday, December 27, 2018 12:20 PM
    Thursday, December 27, 2018 12:18 PM
  • thanks..

    BUT

    I can not use this kind of data structure.

    The data structure is given.

    anyway, thanks again

    (The main question is simplified form of the real one)



    Thursday, December 27, 2018 12:27 PM
  • Check this too:

    var myResult = myList
        .GroupBy( x => x[0] )
        .SelectMany( g => g.Select( i => new { Name = i[0], Letter = i[1], Count = g.Count() } ) );
    
    MessageBox.Show( string.Join( "\n", myResult.Select( z => $"{z.Name} {z.Letter} {z.Count}" ) ) );


    Instead of this convenient unnamed class that contains Name, Letter and Count, you can also build a List<List<string>>.

    Another variant to consider depending on your needs:

    var myResult2 = myList
        .GroupBy( x => x[0] )
        .Select( g => new { Name = g.Key, Letters = g.Select( i => i[1] ) } ); // (Count can be deduced from Letters)



    • Edited by Viorel_MVP Thursday, December 27, 2018 12:43 PM
    Thursday, December 27, 2018 12:32 PM
  • Try this:

    var myResult2 = myList
        .GroupBy( x => x[0] )
        .Select( g => new { Name = g.Key, Letters = g.Select( i => i[1] ) } ).ToList();
    
    MessageBox.Show( string.Join( "\n", myResult2.SelectMany( z => z.Letters.Select( i => $"{z.Name} {i} {z.Letters.Count()}" ) ) ) );
    

    Thursday, December 27, 2018 1:31 PM
  • I have changed some of yours (Your 2nd tip is good !)

    And make this 'nice' result.

    Tanks again !!

    List<List<string>> myList = new List<List<string>> { new List<string> {"Quick", "a" }, new List<string> {"Brown", "b" }, new List<string> {"Fox", "c"}, new List<string> {"Fox", "d"}, new List<string> {"Fox", "e"}, new List<string> {"Jumps", "f" }}; var myResult2 = myList .GroupBy(x => x[0]) .Select(g => new { Name = g.Key, Letter = g.Select(h => new List<string> { h[0], h[1], g.Count().ToString() }) }) .OrderByDescending(x => x.Letter.Count());

    MessageBox.Show(string.Join("\n", myResult2.Select(x => string.Join("\n", x.Letter.Select(y => string.Join(" ", y))))));






    Thursday, December 27, 2018 1:34 PM