使用linq对int数组进行排序?

时间:2015-10-24 10:50:45

标签: c# arrays linq sorting

问题

编写程序对任何给定的正数和负数整数数组进行排序,使得正数跟随负数,但正数和负数的相对位置保持不变。如下面的示例(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,-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 ++的解决方案也很好。

4 个答案:

答案 0 :(得分:3)

根据this OrderBy稳定如此:

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

答案 1 :(得分:1)

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();
}

答案 2 :(得分:0)

根本不需要分组。 Linq-to-objects是稳定的&#34; (meainig在使用OrderBy时会保留&#34;重复&#34;对象的原始顺序,因此您可以根据数字是否小于零进行排序:

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<int>,则可以避免ToArray调用并减少内存使用量。

您是否将Linq订购计算为&#34;迭代一次&#34;取决于谁给了你这个要求。我不知道任何可以一次完成的排序算法。

  

使用或不使用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;
} 

答案 3 :(得分:0)

我喜欢这些:

按升序排序

enumerable.OrderBy(x => x);

按降序排列

enumerable.OrderByDescending(x => x);