命名用于比较两个排序列表的算法?

时间:2009-02-15 16:23:21

标签: c# linq

我有一个algorithm that compares two sorted lists,我打算更多地使用LINQ-y。

我的第一个问题:LINQ中有这样的东西吗?

如果没有,我打算将其作为扩展方法编写,如下所示:

public static class SortedCompareExtension
{
    public static IEnumerable<Pair<T, U>>
        CompareTo<T,U>(this IEnumerable<T> left,
                       IEnumerable<U> right,
                       Func<T, U, int> comparison)
    { /* ... */ }
}

如果两个元素都是等价的,它将返回new Pair<T, U>(t, u),如果元素仅存在于左侧列表中,则返回new Pair<T, U>(t, null),等等。

我的第二个问题:CompareTo对此不是一个好名字。它是什么?是比较,整理,关联?什么?

4 个答案:

答案 0 :(得分:4)

你是Synchronizing列表,虽然名称有不一致的线程同步内容。

我会说'ReconcileOrdered'(可能是OrderedReconcile)是一个合理的名称(在函数名称中指明参数必须都被命令才能使其正常运行可能非常重要

答案 1 :(得分:1)

Diff怎么样?我不相信LINQ中已有任何东西可以做任何事情,但有ExceptIntersect。听起来你的代码大多是两者的混合 - 除了那些 set 操作,而你已经有了排序列表。它主要是效率的一种情况,还是在你的情况下存在语义差异? (一个例子是重复输入。)

就我个人而言,我不确定在这种情况下我会使用一对。只涉及一个价值,不是吗?是不是真的是Value,PresentInLeft(bool)和PresentInRight(bool)?我确信每个表示都有它的优点和缺点,你当然可以从相同的底层数据中公开API ......

答案 2 :(得分:0)

链接的算法非常接近“Full Outer Merge Join”。它的不同之处仅在于如何处理重复项。

  

LINQ中有这样的东西吗?

     

如果两个元素都是等价的,它将返回新的Pair(t,u),如果元素只存在于左侧列表中,则返回new Pair(t,null),等等。

仅从左侧开始,GroupJoin类似。

答案 3 :(得分:0)

这是我最终得到的代码。我非常喜欢它,特别是选择器,这意味着调用者可以决定在每个场景中返回什么:

public static class OrderedReconcileExtension
{
    public static IEnumerable<TResult>
        ReconcileWith<T, U, TResult>(this IEnumerable<T> left,
                                     IEnumerable<U> right,
                                     Func<T, U, int> comparison,
                                     Func<T, U, TResult> selector)
    {
        return ReconcileHelper(new EnumerableIterator<T>(left),
                               new EnumerableIterator<U>(right),
                               comparison, selector);
    }

    private static IEnumerable<TResult>
        ReconcileHelper<T, U, TResult>(EnumerableIterator<T> left,
                                       EnumerableIterator<U> right,
                                       Func<T, U, int> comparison,
                                       Func<T, U, TResult> selector)
    {
        while (left.IsValid && right.IsValid)
        {
            // While left < right, the items in left aren't in right
            while (left.IsValid && right.IsValid && 
                   comparison(left.Current, right.Current) < 0)
            {
                yield return selector(left.Current, default(U));
                left.MoveNext();
            }

            // While right < left, the items in right aren't in left
            while (left.IsValid && right.IsValid &&
                   comparison(left.Current, right.Current) > 0)
            {
                yield return selector(default(T), right.Current);
                right.MoveNext();
            }

            // While left == right, the items are in both
            while (left.IsValid && right.IsValid &&
                   comparison(left.Current, right.Current) == 0)
            {
                yield return selector(left.Current, right.Current);
                left.MoveNext();
                right.MoveNext();
            }
        }

        // Mop up.
        while (left.IsValid)
        {
            yield return selector(left.Current, default(U));
            left.MoveNext();
        }

        while (right.IsValid)
        {
            yield return selector(default(T), right.Current);
            right.MoveNext();
        }
    }
}

EnumerableIterator与我在其他问题中发布的代码完全相同。

更新:除了IsValid之外,“完全相同”更改为HasCurrent。选一个。