【问题标题】:Naming an algorithm for comparing two sorted lists?命名用于比较两个排序列表的算法?
【发布时间】:2009-09-11 22:49:47
【问题描述】:

我有一个 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&lt;T, U&gt;(t, u),如果元素只存在于左侧列表中,则返回new Pair&lt;T, U&gt;(t, null),等等。

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

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    你是Synchronizing列表,虽然名字有线程同步的不幸含义。

    我会说“ReconcileOrdered”(可能是 OrderedReconcile)是一个合理的名称(在函数名称中指出必须对参数进行排序以使其行为正确可能非常重要

    【讨论】:

    • 我喜欢“和解”。我想我会选择 OrderedReconcileWith()。
    【解决方案2】:

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

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

    【讨论】:

    • 这是为了效率。 IEnumerable 实际上可能存在于网络连接的另一端(从服务器返回),并且可能非常大,所以我在协程中生成它们。
    • 即使一个值出现在两个列表中,它可能仍然需要同步(例如,如果只比较一个或两个属性,其他属性可能需要协调),所以我需要两者。
    • 好的,所以这只是一种投影等价,而不是整个实体的等价。这很公平。
    【解决方案3】:

    链接的算法非常接近“完全外部合并连接”。不同之处仅在于如何处理重复项。

    在 LINQ 中已经有类似的东西了吗?

    如果两个元素相等,则返回 new Pair(t, u),如果元素仅存在于左侧列表中,则返回 new Pair(t, null),等等。

    仅从左侧看,GroupJoin 类似。

    【讨论】:

      【解决方案4】:

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

      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。选择一个。

      【讨论】:

        猜你喜欢
        • 2015-07-19
        • 2013-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多