G. H.
G. H.

Reputation: 35

Use linq to remove elements in one list using a condition in another

I have

List<X> A = new List<X>{null,"1",null,"3"};
List<Y> B = new List<Y>{  0 , 1 ,  2 , 3 };

I want to use linq to list only the elemnts in B that have a corresponding value in A that is not null. so...

List<Y> C = [some linq expression using A and B];

C now has 1 and 3 in it.

How can this be done?

Upvotes: 1

Views: 313

Answers (6)

Trioj
Trioj

Reputation: 303

Edit to note that it was unclear to me when this was written that both lists are aligned by index. Unsure of the value of this response given that information. It's certainly less valuable than I initially imagined.

Essentially what you want is an intersection. Here's an answer using Intersect() that works based on the data and parameters supplied in your example:

    var a = new List<string> { null, "1", null, "3" };
    var b = new List<int> { 0, 1, 2, 3 };
    var intersection = a.Intersect(b.Select(x => x.ToString())).ToList();

You should be able to adapt to an intersection that works for you.

If both of your lists really have nullable items in them, then you'll need additional null checks on the b list (I'm just blindly calling ToString() on each item in it). But there's no reason to filter out nulls in A if B contains no nulls and you are doing an intersection, they will be filtered out as part of that process.

Consider also that:

    b.Select(x => x.ToString()) ...

Could very easily be:

    b.Select(x => ConvertTypeBToTypeA(x)) ...

Upvotes: 2

Ousmane D.
Ousmane D.

Reputation: 56413

try this:

var c = Enumerable.Range(0, Math.Min(B.Count, A.Count))
                  .Where(i => A[i] != null)
                  .Select(i => B[i]).ToList();

Upvotes: 0

NetMage
NetMage

Reputation: 26907

How about an extension method to avoid some overhead?

public static class Ext {
    public static IEnumerable<T1> WhereOther<T1, T2>(this IEnumerable<T1> src, IEnumerable<T2> filter, Func<T2, bool> pred) {
        using (var isrc = src.GetEnumerator())
        using (var ifilter = filter.GetEnumerator())
            while (ifilter.MoveNext())
                if (isrc.MoveNext())
                    if (pred(ifilter.Current))
                        yield return isrc.Current;

    }
}

With that created, you can use

var ans = B.WhereOther(A, p => p != null);

You may also want an IQueryable variant, though creating one isn't that easy. I guess you could cheat and return a lambda that applies AsEnumerable() and then uses IEnumerable.WhereOther.

Upvotes: 0

Yuriy Faktorovich
Yuriy Faktorovich

Reputation: 68667

var c = B.Where((o, i) => A[i] != null).ToList();

Upvotes: 3

Tiago &#193;vila
Tiago &#193;vila

Reputation: 2867

List<string> A = new List<string> { null, "1", null, "3" };
List<int> B = new List<int> { 0, 1, 2, 3 };

var C = B.Where(x => A.Contains(x.ToString()));

Upvotes: 1

List<String> A = new List<String> { null, "1", null, "3" };
List<int> B = new List<int> { 0, 1, 2, 3 };

var C = A.Zip(B, (s, n) => new { a = s, b = n })
         .Where(x => x.a != null)
         .Select(x => x.b)
         .ToList();

Upvotes: 4

Related Questions