【问题标题】:Sort int array using linq?使用linq对int数组进行排序?
【发布时间】:2017-02-16 13:01:43
【问题描述】:

问题

编写一个程序对任何给定的正负数整数数组进行排序,使得正数跟随负数,但是正数和负数的相对位置保持不变。就像下面的示例 (1) 一样,(-7) 出现在 (-5) 之后,因此在排序数组中 (-7) 出现在 (-5) 之后。

程序应该只迭代给定数组一次,并且不应该使用临时数组。

示例 1。 给定数组:{ 2, 4, -5, 0, -7, -2, 2, -5, 1, -9, -7, -1 }

排序数组:{ -5, -7, -2, -5, -9, -7, -1, 2, 4, 0, 2, 1 }

示例 2。 给定数组:{ -3, 7, 0, -2, -1, 3, -3, 9, 5, -5, 8}

排序数组:{ -3, -2, -1, -3, -5, 7, 0, 3, 9, 5 , 8}

我的解决方案

class Program
{
    public static void Main(string[] args)
    {
        var intArray = new int[] {  2, 4, -5, 0, -7, -2, 2, -5, 1, -9, -7, -1 };
        var sorted_intArray = SortIntArray(intArray);
        Console.WriteLine(String.Join(",", sorted_intArray));

        intArray = new int[] { -3, -2, -1, -3, -5, 7, 0, 3, 9, 5, 8 };
        sorted_intArray = SortIntArray(intArray);
        Console.WriteLine(String.Join(",", sorted_intArray));
        Console.ReadLine();
    }

    private static int[] SortIntArray(int[] intArray)
    {
        var sorted_intArray = intArray.GroupBy(_int => _int < 0 ? -1 : 1)// Create group of +ve and -ve numbers
                             .OrderBy(group => group.Key)  // Bring group of -ve number first
                             .SelectMany(groupedItems => groupedItems).ToArray(); // Select num from both Group and convert to array
        return sorted_intArray;
    }
}

问题

i) 问题陈述说,数字应该只迭代一次,并且不应该使用临时数组。我相信我使用 linq 的解决方案不符合这个要求。如果可能的话,如何用 linq 解决上述问题?

ii) 在使用或不使用 linq 的情况下,解决上述问题的其他可能且有效的方法是什么?使用 C/C++ 的解决方案也很好。

【问题讨论】:

  • 有一个可能的解决方案是在扩展方法中创建一个临时数据结构。我看不出没有临时工怎么解决。存储给定您想要(输入?)数字的正整数的数据结构迭代一次,对吧?这样输出数字可以迭代一次
  • 看起来像 this question 的副本
  • 您实际上并没有多次迭代数组。你只迭代一次。

标签: c# arrays linq sorting


【解决方案1】:

根据this OrderBy 是稳定的所以:

enumerable.OrderBy(x => x >= 0);

【讨论】:

  • @Hakam 刚刚用 linqpad 中的示例尝试了代码,它工作正常。试试看。
  • 是的,你是对的。这一定是公认的答案,因为它非常非常简单和优雅
  • 你可以简单地做 enumerable.OrderBy(x=>x);
【解决方案2】:

我喜欢这个:

升序排列

enumerable.OrderBy(x => x);

降序排列

enumerable.OrderByDescending(x => x);

【讨论】:

    【解决方案3】:

    Linq 太棒了:

    private static int[] SortIntArrayWithDuplicates(IEnumerable<int> intArray)
    {
        var enumerable = intArray as int[] ?? intArray.ToArray();
    
        return enumerable.Where(x => x < 0)
            .Concat(enumerable.Where(x => x >= 0))
            .ToArray();
    }
    
    private static int[] SortIntArrayWithoutDuplicates(IEnumerable<int> intArray)
    {
        var enumerable = intArray as int[] ?? intArray.ToArray();
    
        return enumerable.Where(x => x < 0)
            .Union(enumerable.Where(x => x >= 0))
            .ToArray();
    }
    

    【讨论】:

      【解决方案4】:

      您根本不需要分组。当使用OrderBy 时,Linq-to-objects 是“稳定的”(意味着它保持“重复”对象的原始顺序),因此您可以只订购数字是否小于零:

      private static int[] SortIntArray(int[] intArray)
      {
          var sorted_intArray = intArray.OrderBy(i => i < 0 ? 0 : 1).ToArray(); 
          return sorted_intArray;
      }
      

      输出:

      -5,-7,-2,-5,-9,-7,-1,2,4,0,2,1
      -3,-2,-1,-3,-5,7,0,3,9,5,8
      

      请注意,如果您将返回类型更改为IEnumerable&lt;int&gt;,则可以避免ToArray 调用并减少内存使用量。

      您是否将 Linq 排序视为“迭代一次”取决于给您该要求的人。我不知道有什么排序算法可以一次性完成。

      在使用或不使用 linq 的情况下,解决上述问题的其他可能且有效的方法是什么?

      好吧,我可以通过扫描所有数字,首先获取负数,然后再次扫描,获取所有非负数,来了解您如何在 两次 遍中做到这一点。您可以使用yield 语法简化此操作:

      private static IEnumerable<int> SortIntArray(int[] intArray)
      {
          foreach(var i in intArray)
              if(i < 0) yield return i;
          foreach(var i in intArray)
              if(i >= 0) yield return i;
      } 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-23
        • 2011-03-12
        相关资源
        最近更新 更多