Click here to Skip to main content
15,885,171 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi I have following collection

C#
List<List<string>> Test_List = new List<List<string>>();

           List<string> a = new List<string> { "1", "2", "1", "1", "3" };
           List<string> b = new List<string>{ "11", "12", "11", "11", "13" };
           List<string> c = new List<string>{ "21", "22", "21", "21", "23" };
           List<string> d = new List<string> { "31", "32", "31", "31", "33" };

           Test_List.Add(a);
           Test_List.Add(b);
           Test_List.Add(c);
           Test_List.Add(d);


I want to get a new list that would contain a value repeated highest time in each element of Test_list for e.g. In above case a,b,c,d are element of Test_list, we see 1 has repeated highest time in a, like wise 11 in b, 21 in c and 31 in d.
I want to get a new list or array that would contain 1,11,21,31 in it. I want Linq solution without any loop.

I tried with
C#
var res = Test_List.Select(n=>n).Select(l=>l).GroupBy(m => m).Select(g => new { count = g.Count(), value = g.Key }).OrderByDescending(u=> u.count).Select(h=>h.value).ToArray();


But above code did not work for me.
Thanks
Posted
Updated 15-May-14 9:09am
v2

You were nearly there:
C#
var res = Test_List.Select(tl => tl.GroupBy(t => t).Select(g => new { val = g.Key, cnt = g.Count() }).OrderByDescending(o => o.cnt).ToArray()[0].val);
 
Share this answer
 
Comments
Sander Rossel 15-May-14 15:06pm    
My vote of 1, you just beat me to it (j/k gave a 5)! ;-)
I guess more or less the same solution as I have, just written differently :-)
rameshKumar1717 17-May-14 2:13am    
This solution exactly I was looking for single line without any loop. thanks
OriginalGriff 17-May-14 2:26am    
You're welcome!
Well, one solution could be the following:
C#
List<string> doubles = Test_List.SelectMany(l => l).ToLookup(s => s).Where(g => g.Count() > 1).Select(g => g.Key).ToList();

// Complete step-by-step explanation:

// First we use SelectMany to combine the strings in all our lists to a single list.
IEnumerable<string> first = Test_List.SelectMany(l => l);
// Next we create a lookup, having the string as a key and all the occurrences of that string as a value.
ILookup<string, string> next = first.ToLookup(s => s);
// After that we filter this lookup grabbing all entries that has more than 1 value (meaning more than one
// occurrence in the original list).
IEnumerable<IGrouping<string, string>> afterThat = next.Where(g => g.Count() > 1);
// Then we select the original string, using the keys of the lookup.
IEnumerable<string> then = afterThat.Select(g => g.Key);
// Last we create a list (or array) to hold the items. You could add ordering etc.
List<string> last = then.ToList();
I'm not saying this is the best way to do it (with LINQ there are usually more methods to get to the same result), but it's one solution and I think it's not to hard to understand :)
 
Share this answer
 
v2
Another approach, 2 steps, straightforward logic, maybe it does the job for someone

C#
Test_List.ForEach(p => p.Sort((x, y) => p.Count(s => s == y).CompareTo(p.Count(s => s == x))));
var q = Test_List.Select(p => p.First()).ToList();
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900