tags:

views:

180

answers:

5

I am a bit new to LINQ, here is my problem.

  • I have a List of List of Items
  • I like to get the Items which are present in only one List (and if I could get the List in which they are without re-iterating through the "list of list" that would be great).

I am trying without success to use the Aggregate / Except / Group keywords in the Linq query but nothing close to a solution so far.

[EDIT] Could be for instance List<List<int>> and the condition that the value of the int is is not in the others lists.

To be honest if I tried with several foreach I succeed to find the value items but as I am trying to learn LINQ I would like to know what kind of query I should write to get the results

for instance

 1,2,6
 1,6
 3,5
 5,10
 3,10,6

will return 2 and the first list

+2  A: 
var query = from list in lists
            from value in list
            where lists.Where(l => l.Contains(value)).Count() == 1
            select new { List = list, Value = value };
Roger Alsing
I took that one as it was the simplest and easiest to read valid solutions.Many thanks to John Rasch, Matthew Whited, as their propositions also give correct answers.
call me Steve
+2  A: 

This will get you the unique integers:

var ints = listOfLists.SelectMany(l => l);
var uniques = ints.Where(i => ints.Count(val => val == i) == 1);
John Rasch
+2  A: 
from lst in lists
from i in lst
group lst by i into grp
where grp.Count() == 1
select new { Value = grp.Key, List = grp.Single() };

That will give you the numbers that appear only in 1 list, along with the list that contains it

EDIT: simplified a bit

Thomas Levesque
I tried that proposition, but it didn't give the expected results (on the test sample it return empty).
call me Steve
I tried it with your sample data before I posted it, it worked fine for me... It's also much more efficient than the solution you accepted
Thomas Levesque
Just tried again, I confirm it works fine... It returns 2 with the list containing 2
Thomas Levesque
A: 

Looks like I came up with the same solution as Thomas, just using the functional syntax...

var uniques = listlist.SelectMany(l => l.Select(i => new {Item = i, Origin = l}))
                      .GroupBy(i => i.Item)
                      .Where(g => g.Count() == 1)
                      .Select(g => g.First());

Note that all of our solutions assume that the numbers within each list are already distinct; i.e. if a single list contains a repeated value that isn't in any of the others, it'll still get rejected.

tzaman
+1  A: 

var sets = new[] { "1,2,6", "1,6", "3,5,9", "5,10", "3,10,6" };

var grouped = sets.SelectMany(i => i.Split(','))
                  .GroupBy(i => i)
                  .Where(i => i.Count() == 1)
                  .Select(i => i.Key);

Console.WriteLine(string.Join(", ", grouped.ToArray())); //2, 9
Matthew Whited