PC Review


Reply
Thread Tools Rate Thread

Collection Intersection Helper

 
 
Shapper
Guest
Posts: n/a
 
      19th Jan 2011
Hello,

I have two lists of an object:

List<ObjectA> As;
List<ObjectB> Bs;

Is it possible to create one or more methods or extensions that would
make possible to get 3 lists:

List 1 - All objects existing in list A but not in B
List 2 - All objects existing in list B but not in A
List 3 - All objects existing in both Lists.

Basically what I am trying to get is:
A intersection B
A intersection Not B
Not A intersection with B

I would like to define the condition that makes the intersection.
Maybe with a lambda expression?
Does this make sense?

Thank You,
Miguel
 
Reply With Quote
 
 
 
 
Arne Vajhøj
Guest
Posts: n/a
 
      20th Jan 2011
On 19-01-2011 18:04, Shapper wrote:
> I have two lists of an object:
>
> List<ObjectA> As;
> List<ObjectB> Bs;
>
> Is it possible to create one or more methods or extensions that would
> make possible to get 3 lists:
>
> List 1 - All objects existing in list A but not in B
> List 2 - All objects existing in list B but not in A
> List 3 - All objects existing in both Lists.
>
> Basically what I am trying to get is:
> A intersection B
> A intersection Not B
> Not A intersection with B
>
> I would like to define the condition that makes the intersection.
> Maybe with a lambda expression?
> Does this make sense?


It is easy for:

List<ObjectX> As;
List<ObjectX> Bs;

(standard LINQ has methods for that)

but for lists of different types I don't think it
makes much sense.

Arne


 
Reply With Quote
 
kndg
Guest
Posts: n/a
 
      20th Jan 2011
On 1/20/2011 7:04 AM, Shapper wrote:
> Hello,
>
> I have two lists of an object:
>
> List<ObjectA> As;
> List<ObjectB> Bs;
>
> Is it possible to create one or more methods or extensions that would
> make possible to get 3 lists:
>
> List 1 - All objects existing in list A but not in B
> List 2 - All objects existing in list B but not in A
> List 3 - All objects existing in both Lists.
>
> Basically what I am trying to get is:
> A intersection B
> A intersection Not B
> Not A intersection with B
>
> I would like to define the condition that makes the intersection.
> Maybe with a lambda expression?
> Does this make sense?
>
> Thank You,
> Miguel


I would look into HashSet<T> instead. It has all your required operation.
 
Reply With Quote
 
Arne Vajhøj
Guest
Posts: n/a
 
      20th Jan 2011
On 19-01-2011 19:54, Arne Vajhøj wrote:
> On 19-01-2011 18:04, Shapper wrote:
>> I have two lists of an object:
>>
>> List<ObjectA> As;
>> List<ObjectB> Bs;
>>
>> Is it possible to create one or more methods or extensions that would
>> make possible to get 3 lists:
>>
>> List 1 - All objects existing in list A but not in B
>> List 2 - All objects existing in list B but not in A
>> List 3 - All objects existing in both Lists.
>>
>> Basically what I am trying to get is:
>> A intersection B
>> A intersection Not B
>> Not A intersection with B
>>
>> I would like to define the condition that makes the intersection.
>> Maybe with a lambda expression?
>> Does this make sense?

>
> It is easy for:
>
> List<ObjectX> As;
> List<ObjectX> Bs;
>
> (standard LINQ has methods for that)
>
> but for lists of different types I don't think it
> makes much sense.


Demo with same type:

using System;
using System.Collections.Generic;
using System.Linq;

namespace E
{
public class Program
{
public static void Main(string[] args)
{
List<string> x = new List<string>{ "A", "B", "C", "D" };
List<string> y = new List<string>{ "C", "D", "E", "F" };
foreach(string s in x.Except(y))
{
Console.Write(" " + s);
}
Console.WriteLine();
foreach(string s in y.Except(x))
{
Console.Write(" " + s);
}
Console.WriteLine();
foreach(string s in x.Intersect(y))
{
Console.Write(" " + s);
}
Console.WriteLine();
foreach(string s in x.Union(y))
{
Console.Write(" " + s);
}
Console.WriteLine();
Console.ReadKey();
}
}
}

Arne
 
Reply With Quote
 
Arne Vajhøj
Guest
Posts: n/a
 
      20th Jan 2011
On 19-01-2011 20:20, kndg wrote:
> On 1/20/2011 7:04 AM, Shapper wrote:
>> I have two lists of an object:
>>
>> List<ObjectA> As;
>> List<ObjectB> Bs;
>>
>> Is it possible to create one or more methods or extensions that would
>> make possible to get 3 lists:
>>
>> List 1 - All objects existing in list A but not in B
>> List 2 - All objects existing in list B but not in A
>> List 3 - All objects existing in both Lists.
>>
>> Basically what I am trying to get is:
>> A intersection B
>> A intersection Not B
>> Not A intersection with B
>>
>> I would like to define the condition that makes the intersection.
>> Maybe with a lambda expression?
>> Does this make sense?

>
> I would look into HashSet<T> instead. It has all your required operation.


Not only does HashSet<T> have them, but it would also be very
fast at doing them.

But it also have slightly different characteristics than List<T>.

Duplicates. Order. Access by index.

Arne

 
Reply With Quote
 
Arne Vajhøj
Guest
Posts: n/a
 
      20th Jan 2011
On 19-01-2011 20:43, Arne Vajhøj wrote:
> On 19-01-2011 19:54, Arne Vajhøj wrote:
>> On 19-01-2011 18:04, Shapper wrote:
>>> I have two lists of an object:
>>>
>>> List<ObjectA> As;
>>> List<ObjectB> Bs;
>>>
>>> Is it possible to create one or more methods or extensions that would
>>> make possible to get 3 lists:
>>>
>>> List 1 - All objects existing in list A but not in B
>>> List 2 - All objects existing in list B but not in A
>>> List 3 - All objects existing in both Lists.
>>>
>>> Basically what I am trying to get is:
>>> A intersection B
>>> A intersection Not B
>>> Not A intersection with B
>>>
>>> I would like to define the condition that makes the intersection.
>>> Maybe with a lambda expression?
>>> Does this make sense?

>>
>> It is easy for:
>>
>> List<ObjectX> As;
>> List<ObjectX> Bs;
>>
>> (standard LINQ has methods for that)
>>
>> but for lists of different types I don't think it
>> makes much sense.

>
> Demo with same type:
>
> using System;
> using System.Collections.Generic;
> using System.Linq;
>
> namespace E
> {
> public class Program
> {
> public static void Main(string[] args)
> {
> List<string> x = new List<string>{ "A", "B", "C", "D" };
> List<string> y = new List<string>{ "C", "D", "E", "F" };
> foreach(string s in x.Except(y))
> {
> Console.Write(" " + s);
> }
> Console.WriteLine();
> foreach(string s in y.Except(x))
> {
> Console.Write(" " + s);
> }
> Console.WriteLine();
> foreach(string s in x.Intersect(y))
> {
> Console.Write(" " + s);
> }
> Console.WriteLine();
> foreach(string s in x.Union(y))
> {
> Console.Write(" " + s);
> }
> Console.WriteLine();
> Console.ReadKey();
> }
> }
> }


And:

foreach(string s in x.Concat(y))
{
Console.Write(" " + s);
}
Console.WriteLine();

if so needed.

Arne
 
Reply With Quote
 
Shapper
Guest
Posts: n/a
 
      20th Jan 2011
On Jan 20, 1:47*am, Arne Vajhøj <a...@vajhoej.dk> wrote:
> On 19-01-2011 20:43, Arne Vajhøj wrote:
>
>
>
> > On 19-01-2011 19:54, Arne Vajhøj wrote:
> >> On 19-01-2011 18:04, Shapper wrote:
> >>> I have two lists of an object:

>
> >>> List<ObjectA> As;
> >>> List<ObjectB> Bs;

>
> >>> Is it possible to create one or more methods or extensions that would
> >>> make possible to get 3 lists:

>
> >>> List 1 - All objects existing in list A but not in B
> >>> List 2 - All objects existing in list B but not in A
> >>> List 3 - All objects existing in both Lists.

>
> >>> Basically what I am trying to get is:
> >>> A intersection B
> >>> A intersection Not B
> >>> Not A intersection with B

>
> >>> I would like to define the condition that makes the intersection.
> >>> Maybe with a lambda expression?
> >>> Does this make sense?

>
> >> It is easy for:

>
> >> List<ObjectX> As;
> >> List<ObjectX> Bs;

>
> >> (standard LINQ has methods for that)

>
> >> but for lists of different types I don't think it
> >> makes much sense.

>
> > Demo with same type:

>
> > using System;
> > using System.Collections.Generic;
> > using System.Linq;

>
> > namespace E
> > {
> > public class Program
> > {
> > public static void Main(string[] args)
> > {
> > List<string> x = new List<string>{ "A", "B", "C", "D" };
> > List<string> y = new List<string>{ "C", "D", "E", "F" };
> > foreach(string s in x.Except(y))
> > {
> > Console.Write(" " + s);
> > }
> > Console.WriteLine();
> > foreach(string s in y.Except(x))
> > {
> > Console.Write(" " + s);
> > }
> > Console.WriteLine();
> > foreach(string s in x.Intersect(y))
> > {
> > Console.Write(" " + s);
> > }
> > Console.WriteLine();
> > foreach(string s in x.Union(y))
> > {
> > Console.Write(" " + s);
> > }
> > Console.WriteLine();
> > Console.ReadKey();
> > }
> > }
> > }

>
> And:
>
> * * * * * * *foreach(string s in x.Concat(y))
> * * * * * * *{
> * * * * * * * * *Console.Write(" " + s);
> * * * * * * *}
> * * * * * * *Console.WriteLine();
>
> if so needed.
>
> Arne


Hello,

Yes, it can be objects with same type. But what do you mean with
x.Except(y)?

I need to define the condition. Something like:

x.Except(x => y.Id == x.Id)

This is the kind of helper I was looking for.

 
Reply With Quote
 
Arne Vajhøj
Guest
Posts: n/a
 
      21st Jan 2011
On 20-01-2011 11:07, Shapper wrote:
> On Jan 20, 1:47 am, Arne Vajhøj<a...@vajhoej.dk> wrote:
>> On 19-01-2011 20:43, Arne Vajhøj wrote:
>>
>>
>>
>>> On 19-01-2011 19:54, Arne Vajhøj wrote:
>>>> On 19-01-2011 18:04, Shapper wrote:
>>>>> I have two lists of an object:

>>
>>>>> List<ObjectA> As;
>>>>> List<ObjectB> Bs;

>>
>>>>> Is it possible to create one or more methods or extensions that would
>>>>> make possible to get 3 lists:

>>
>>>>> List 1 - All objects existing in list A but not in B
>>>>> List 2 - All objects existing in list B but not in A
>>>>> List 3 - All objects existing in both Lists.

>>
>>>>> Basically what I am trying to get is:
>>>>> A intersection B
>>>>> A intersection Not B
>>>>> Not A intersection with B

>>
>>>>> I would like to define the condition that makes the intersection.
>>>>> Maybe with a lambda expression?
>>>>> Does this make sense?

>>
>>>> It is easy for:

>>
>>>> List<ObjectX> As;
>>>> List<ObjectX> Bs;

>>
>>>> (standard LINQ has methods for that)

>>
>>>> but for lists of different types I don't think it
>>>> makes much sense.

>>
>>> Demo with same type:

>>
>>> using System;
>>> using System.Collections.Generic;
>>> using System.Linq;

>>
>>> namespace E
>>> {
>>> public class Program
>>> {
>>> public static void Main(string[] args)
>>> {
>>> List<string> x = new List<string>{ "A", "B", "C", "D" };
>>> List<string> y = new List<string>{ "C", "D", "E", "F" };
>>> foreach(string s in x.Except(y))
>>> {
>>> Console.Write(" " + s);
>>> }
>>> Console.WriteLine();
>>> foreach(string s in y.Except(x))
>>> {
>>> Console.Write(" " + s);
>>> }
>>> Console.WriteLine();
>>> foreach(string s in x.Intersect(y))
>>> {
>>> Console.Write(" " + s);
>>> }
>>> Console.WriteLine();
>>> foreach(string s in x.Union(y))
>>> {
>>> Console.Write(" " + s);
>>> }
>>> Console.WriteLine();
>>> Console.ReadKey();
>>> }
>>> }
>>> }

>>
>> And:
>>
>> foreach(string s in x.Concat(y))
>> {
>> Console.Write(" " + s);
>> }
>> Console.WriteLine();
>>
>> if so needed.

> Yes, it can be objects with same type. But what do you mean with
> x.Except(y)?
>
> I need to define the condition. Something like:
>
> x.Except(x => y.Id == x.Id)
>
> This is the kind of helper I was looking for.


This is going to be a little bit long, but ...

Let us look at this code:

using System;
using System.Collections.Generic;
using System.Linq;

namespace E
{
public class Person
{
private string name;
private string address;
public Person(string name, string address)
{
this.name = name;
this.address = address;
}
public string Name
{
get { return name; }
}
public string Address
{
get { return address; }
}
public override string ToString()
{
return name + "/" + address;
}
}
public class Program
{
public static void Main(string[] args)
{
List<Person> x = new List<Person>();
x.Add(new Person("A A", "aa aa aa aa"));
x.Add(new Person("B B", "bbb bbb bbb"));
x.Add(new Person("C C", "cccc cccc"));
List<Person> y = new List<Person>();
y.Add(new Person("C C", "cccc cccc"));
y.Add(new Person("D D", "ddddd"));
Console.WriteLine("x:");
foreach(Person p in x)
{
Console.WriteLine(" " + p);
}
Console.WriteLine("y:");
foreach(Person p in y)
{
Console.WriteLine(" " + p);
}
Console.WriteLine("x except y:");
foreach(Person p in x.Except(y))
{
Console.WriteLine(" " + p);
}
Console.ReadKey();
}
}
}

it outputs:

x:
A A/aa aa aa aa
B B/bbb bbb bbb
C C/cccc cccc
y:
C C/cccc cccc
D D/ddddd
x except y:
A A/aa aa aa aa
B B/bbb bbb bbb
C C/cccc cccc

which as first looks surprising. The problem is that .NET
does not have any way of knowing that two persons with the
name "C C" are actually identical.

There are two ways of solving that.

1) Explicit tell it how to compare in the Except method.

using System;
using System.Collections.Generic;
using System.Linq;

namespace E
{
public class Person
{
private string name;
private string address;
public Person(string name, string address)
{
this.name = name;
this.address = address;
}
public string Name
{
get { return name; }
}
public string Address
{
get { return address; }
}
public override string ToString()
{
return name + "/" + address;
}
}
public class PersonEqualityComparer : IEqualityComparer<Person>
{

public bool Equals(Person x, Person y)
{
return x.Name == y.Name;
}
public int GetHashCode(Person obj)
{
return obj.Name.GetHashCode();
}
}
public class Program
{
public static void Main(string[] args)
{
List<Person> x = new List<Person>();
x.Add(new Person("A A", "aa aa aa aa"));
x.Add(new Person("B B", "bbb bbb bbb"));
x.Add(new Person("C C", "cccc cccc"));
List<Person> y = new List<Person>();
y.Add(new Person("C C", "cccc cccc"));
y.Add(new Person("D D", "ddddd"));
Console.WriteLine("x:");
foreach(Person p in x)
{
Console.WriteLine(" " + p);
}
Console.WriteLine("y:");
foreach(Person p in y)
{
Console.WriteLine(" " + p);
}
Console.WriteLine("x except y:");
foreach(Person p in x.Except(y, new PersonEqualityComparer()))
{
Console.WriteLine(" " + p);
}
Console.ReadKey();
}
}
}

2) Embed in the Person class itself how to compare.

using System;
using System.Collections.Generic;
using System.Linq;

namespace E
{
public class Person
{
private string name;
private string address;
public Person(string name, string address)
{
this.name = name;
this.address = address;
}
public string Name
{
get { return name; }
}
public string Address
{
get { return address; }
}
public override string ToString()
{
return name + "/" + address;
}
public override bool Equals(object obj)
{
return obj.GetType() == typeof(Person) &&
((Person)obj).Name == name;
}
public override int GetHashCode()
{
return name.GetHashCode();
}
}
public class Program
{
public static void Main(string[] args)
{
List<Person> x = new List<Person>();
x.Add(new Person("A A", "aa aa aa aa"));
x.Add(new Person("B B", "bbb bbb bbb"));
x.Add(new Person("C C", "cccc cccc"));
List<Person> y = new List<Person>();
y.Add(new Person("C C", "cccc cccc"));
y.Add(new Person("D D", "ddddd"));
Console.WriteLine("x:");
foreach(Person p in x)
{
Console.WriteLine(" " + p);
}
Console.WriteLine("y:");
foreach(Person p in y)
{
Console.WriteLine(" " + p);
}
Console.WriteLine("x except y:");
foreach(Person p in x.Except(y))
{
Console.WriteLine(" " + p);
}
Console.ReadKey();
}
}
}

If the desired way to compare in Except is a natural way to compare,
then I will recommend the second way, because implementing those
two methods will be useful in a lot of other contexts.

In your specific case then comparing on Id sounds as a natural
comparison.

Arne


 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Collection problems (create Collection object, add data to collection, bind collection to datagrid) Øyvind Isaksen Microsoft ASP .NET 1 18th May 2007 10:24 AM
Collection problems (create Collection object, add data to collection, bind collection to datagrid) Øyvind Isaksen Microsoft Dot NET 1 18th May 2007 10:24 AM
Can't get collection to save when using collection of custom class as property of control in VS 2005 J.Edwards Microsoft Dot NET Compact Framework 0 10th Jan 2006 04:44 AM
key/value collection that allows key string to be updated and retains collection item entry order dx Microsoft Dot NET Framework 2 25th Sep 2004 05:51 PM
Item Collection Editor doesn't preserve collection Andrés Giraldo Microsoft ASP .NET 2 25th Mar 2004 08:38 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 06:50 PM.