LINQ中的完整外部联接针对唯一密钥进行了优化 [英] Full outer Join in LINQ optimized for unique keys

查看:65
本文介绍了LINQ中的完整外部联接针对唯一密钥进行了优化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假定这两个有序序列(元素是唯一的):

Presume these two ordered sequences (the elements are unique):

var outer = new char[] { 'a', 'b', 'c', 'other' };
var inner = new char[] { 'a', 'b', 'c', 'altro' };

所需的结果是完全外部联接:

The desired result is the Full Outer Join:

{ 'a', 'a' }
{ 'b', 'b' }
{ 'c', 'c' }
{ 'other', '' }
{ '', 'altro' }

可以通过LINQ来实现完全外部连接(这是SO的答案): LINQ-完全外部连接

The Full Outer Join can be achieved in LINQ in this way (it's an answer on SO): LINQ - Full Outer Join

但是此解决方案并未考虑到两个序列中的元素都是唯一.如何优化算法?

But this solution doesn't takes in account that the elements from both sequences are unique. How can the algorithm be optimized?

推荐答案

基于引用的答案我尝试了一些不会创建Lookup而是创建Dictionary的东西.

Based on the referenced answer I tried something that doesn't create Lookup's but Dictionary's instead.

恕我直言,这是您唯一可以削减的方法,实际上可以节省一些时间.

IMHO that's the only thing you can cut that will actually save some time.

跳过HashSet的创建(正如我急切的评论中所提议的那样)不是一种选择,因为这将导致所有连接对的重复.

Skipping creation of the HashSet (as proposed in my rushed comment) is not an option as this will lead to the duplication of all joined pairs.

public static class Extensions {
    public static IEnumerable<TResult> FullOuterJoin<TA, TB, TKey, TResult>(
        this IEnumerable<TA> a,
        IEnumerable<TB> b,
        Func<TA, TKey> selectKeyA,
        Func<TB, TKey> selectKeyB,
        Func<TA, TB, TKey, TResult> projection,
        TA defaultA = default(TA),
        TB defaultB = default(TB),
        IEqualityComparer<TKey> cmp = null) {

        cmp = cmp ?? EqualityComparer<TKey>.Default;
        var adict = a.ToDictionary(selectKeyA, cmp);
        var bdict = b.ToDictionary(selectKeyB, cmp);

        var keys = new HashSet<TKey>(adict.Keys, cmp);
        keys.UnionWith(bdict.Keys);

        var join = from key in keys
                   let xa = adict.GetOrDefault(key, defaultA)
                   let xb = bdict.GetOrDefault(key, defaultB)
                   select projection(xa, xb, key);

        return join;
    }

    public static T GetOrDefault<K, T>(this IDictionary<K, T> d, K k, T def = default(T)) 
        => d.TryGetValue(k, out T value) ? value : def;
}

这篇关于LINQ中的完整外部联接针对唯一密钥进行了优化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆