6

2 つList<string>のオブジェクトがある場合、それらに対してIntersectandExceptを直接使用して output を取得できますIEnumerable<string>。それは簡単ですが、もっと複雑なものの交差/分離が必要な場合はどうすればよいでしょうか?

例、オブジェクトのとオブジェクトののClassA交差の結果であるオブジェクトのコレクションを取得しようとしています。:ClassAAStr1ClassBBStr

public class ClassA {
    public string AStr1 { get; set; }
    public string AStr2 { get; set; }
    public int AInt { get; set; }
}
public class ClassB {
    public string BStr { get; set; }
    public int BInt { get; set; }
}
public class Whatever {
    public void xyz(List<ClassA> aObj, List<ClassB> bObj) {
        // *** this line is horribly incorrect ***
        IEnumberable<ClassA> result =
            aObj.Intersect(bObj).Where(a, b => a.AStr1 == b.BStr);
    }
}

この交差を達成するために、注目された線をどのように修正できますか。

4

3 に答える 3

14

MoreLINQにはExceptBy。まだありませんがIntersectBy、独自の実装を簡単に作成でき、後でMoreLINQに貢献することもできます:)

おそらく次のようになります(エラーチェックを省略):

public static IEnumerable<TSource> IntersectBy<TSource, TKey>(
    this IEnumerable<TSource> first,
    IEnumerable<TSource> second,
    Func<TSource, TKey> keySelector,
    IEqualityComparer<TKey> keyComparer)
{
    HashSet<TKey> keys = new HashSet<TKey>(first.Select(keySelector),
                                           keyComparer);
    foreach (var element in second)
    {
        TKey key = keySelector(element);
        // Remove the key so we only yield once
        if (keys.Remove(key))
        {
            yield return element;
        }
    }
}

たまたま共通のプロパティタイプを持つ2つの完全に異なるタイプで交差を実行する場合は、3つのタイプパラメーター(1つは、、1つは、、もう1つは共通キータイプ)を使用して、より一般的なメソッドを作成できfirstますsecond

于 2010-10-22T15:17:38.427 に答える
3

x∈Aおよびx∈Bの場合に限り、x∈A∩B。

したがって、のそれぞれaについて、が値のセットに含まれているaObjかどうかを確認できます。a.AStr1BStr

public void xyz(List<ClassA> aObj, List<ClassB> bObj)
{
    HashSet<string> bstr = new HashSet<string>(bObj.Select(b => b.BStr));
    IEnumerable<ClassA> result = aObj.Where(a => bstr.Contains(a.AStr1));
}
于 2010-10-22T15:21:51.380 に答える
1

このコード:

    public IEnumerable<ClassA> xyz(List<ClassA> aObj, List<ClassB> bObj)
    {
        IEnumerable<string> bStrs = bObj.Select(b => b.BStr).Distinct();
        return aObj.Join(bStrs, a => a.AStr1, b => b, (a, b) => a);
    }

次のテストに合格しました。

    [TestMethod]
    public void PropertyIntersectionBasedJoin()
    {
        List<ClassA> aObj = new List<ClassA>()
                                {
                                    new ClassA() { AStr1 = "a" }, 
                                    new ClassA() { AStr1 = "b" }, 
                                    new ClassA() { AStr1 = "c" }
                                };
        List<ClassB> bObj = new List<ClassB>()
                                {
                                    new ClassB() { BStr = "b" }, 
                                    new ClassB() { BStr = "b" }, 
                                    new ClassB() { BStr = "c" }, 
                                    new ClassB() { BStr = "d" }
                                };

        var result = xyz(aObj, bObj);

        Assert.AreEqual(2, result.Count());
        Assert.IsFalse(result.Any(a => a.AStr1 == "a"));
        Assert.IsTrue(result.Any(a => a.AStr1 == "b"));
        Assert.IsTrue(result.Any(a => a.AStr1 == "c"));
    }
于 2010-10-26T02:06:33.163 に答える