Iterate through 2 lists

I have List<T1>elements and second List<T2>elements. Both lists are sorted alphabetically using property A. I know that the list of elements in List<T2>is a subset List<T1>and that there are no elements in List<T2>that do not exist in List<T1>.

I need to iterate through List<T1>and change the variable every time it matches the variable in List<T2>. What is the fastest and best way to do this? I assume that I need to iterate over both lists, but I know that doing a nested foreach does not make sense.

+5
source share
4 answers

. . .

var super = new List<Contact>();
super.Add(new Contact() {Name = "John"});
super.Add(new Contact() {Name = "Larry"});
super.Add(new Contact() {Name = "Smith"});
super.Add(new Contact() {Name = "Corey"});

var sub = new List<Contact>();
sub.Add(new Contact() {Name = "Larry"});
sub.Add(new Contact() {Name = "Smith"});

var subCount = 0;
for(int i=0; i<super.Count && subCount < sub.Count; i++)
{
    if (super[i].Name == sub[subCount].Name)
    {
        Act(super[i], sub[subCount]);
        subCount++;
    }
}

Act(...) , .

-, , .

, - . 1) 2) - .

+11

, - Contains:

foreach(var item in list1) {
    if (list2.Contains(item) {
        //Do something
    }
}

, BinarySearch IComparer<T>, :

class MyComparer : IComparer<YourClass> {
    private MyComparer() { }
    public static readonly MyComparer Instance = new MyComparer();

    public int CompareTo(YourClass a, YourClass b) {
        //TODO: Handle nulls
        return a.SomeProperty.CompareTo(b.SomeProperty);
    }
}
foreach(var item in list1) {
    if (list2.BinarySearch(item, MyComparer.Instance) >= 0) {
        //Do something
    }
}

.Net 3.5 , HashSet<T>:

var hashset = new HashSet<YourClass>(list2);
foreach(var item in list1) {
    if (hashset.Contains(item) {
        //Do something
    }
}

, .
, .

+5

, . , , , / ( ), .

, :

if (subsetList.Count > 0)
{
    using(IEnumerator<T2> subset = subsetList.GetEnumerator())
    {
        subset.MoveNext();
        T2 subitem = subsetList.Current;
        foreach(T1 item in supersetList)
        {
            while (item.A > subitem.A &&
                   subset.MoveNext())
            {
                subitem = subset.Current;
            }

            if (item.A == subitem.A)
            {
                // Modify item here.
            }
        }
    }
}

, , supersetList subsetList. EndangeredMassa , .

+1

Your question implies that you want to avoid repeating all the elements in the second list every time, which will happen in the worst case solution using the Contains(). Since both lists are sorted and list2a subset list1, you know that no record in list1will have an index smaller than the corresponding record in list2. With that in mind, you can make an effective O (n) solution with two counters:

Debug.Assert(list1.Count > 0);
Debug.Assert(list1.Count >= list2.Count);

var enum1 = list1.GetEnumerator();
var enum2 = list2.GetEnumerator();

enum1.MoveNext();
while (enum2.MoveNext())
{
    // Skip elements from list1 that aren't equal to the current entry in list2
    while (!enum1.Current.Equals(enum2.Current))
        enum1.MoveNext();

    // Fire the OnEqual event for every entry in list1 that equal to an entry
    // in list2
    do {
        OnEqual(enum1.Current, enum2.Current); 
    } while (enum1.MoveNext() && enum1.Current.Equals(enum2.Current));
}

enum1.Dispose();
enum2.Dispose();
+1
source

All Articles