How to perform merge sort using LINQ?

前端 未结 3 759
半阙折子戏
半阙折子戏 2020-12-03 16:04

Assume that you have two IEnumerbale objects. How we can merge them (in some condition e.g merge in merge sort ...) and create a unique IEnumerable

相关标签:
3条回答
  • 2020-12-03 16:49

    Use LINQ method Concat() http://msdn.microsoft.com/en-us/library/bb302894.aspx

    0 讨论(0)
  • 2020-12-03 16:50

    There is no Merge method in System.Linq.Enumerable. If you want one, you have to write it (with a for loop and a yield statement).

    As with many "just by linq" questions - you should assume that every linq method is backed by some plain old .NET code that you could have written yourself.


    Here's an untested freehand non-generic implementation

    public static IEnumerable<int> Merge
    (
    this IEnumerable<int> source1,
    IEnumerable<int> source2
    )
    {
      using(Enumerator<int> e1 = source1.GetEnumerator())
      {
        bool more1 = e1.MoveNext();
        using(Enumerator<int> e2 = source2.GetEnumerator()
        {
          bool more2 = e2.MoveNext();
    
          while (more1 && more2)
          {
            int v1 = e1.Current;
            int v2 = e2.Current;
            if (v1 < v2)
            {
              yield return v1;
              more1 = e1.MoveNext();
            }
            else
            {
              yield return v2;
              more2 = e2.MoveNext();
            }
    
          }
          while (more1 && ! more2)
          {
            yield return e1.Current;
            more1 = e1.MoveNext();
          }
          while (more2 && ! more1)
          {
            yield return e2.Current;
            more2 = e2.MoveNext();
          }
        }
      }
    }
    
    0 讨论(0)
  • 2020-12-03 16:54

    There is no such method in LINQ. And I don't think it's possible to combine the existing methods to do exactly what you want (if it was, it would be overly complicated).

    But implementing such method yourself isn't that hard:

    static IEnumerable<T> Merge<T>(this IEnumerable<T> first,
                                   IEnumerable<T> second,
                                   Func<T, T, bool> predicate)
    {
        // validation ommited
    
        using (var firstEnumerator = first.GetEnumerator())
        using (var secondEnumerator = second.GetEnumerator())
        {
            bool firstCond = firstEnumerator.MoveNext();
            bool secondCond = secondEnumerator.MoveNext();
    
            while (firstCond && secondCond)
            {
                if (predicate(firstEnumerator.Current,  secondEnumerator.Current))
                {
                    yield return firstEnumerator.Current;
                    firstCond = firstEnumerator.MoveNext();
                }
                else
                {
                    yield return secondEnumerator.Current;
                    secondCond = secondEnumerator.MoveNext();
                }
            }
    
            while (firstCond)
            {
                yield return firstEnumerator.Current;
                firstCond = firstEnumerator.MoveNext();
            }
    
            while (secondCond)
            {
                yield return secondEnumerator.Current;
                secondCond = secondEnumerator.MoveNext();
            }
        }
    }
    

    And you could use it like this:

    lst1.Merge(lst2, (i, j) => i < j)
    
    0 讨论(0)
提交回复
热议问题