是否可以在LINQ中表达此代码?

时间:2010-10-21 00:43:13

标签: c# linq

我正在为初学者阅读一本C#书,在本章的每一端,都会根据所学的课程来回答练习。

其中一项练习就是这样:(不是确切的措辞)

编写一个程序,接受一个int作为数组长度,以及数组的值 然后打印:
如果数组未按升序排序,则“ 0 ” “ 1 ”如果已排序。而且,
2 ”如果已排序,但有重复项。

示例:

// Sorted
Input: 1, 2, 3, 5
Print: 1

// Not sorted
Input: 2, 1, 3, 6
Print: 0

// Sorted, but with duplicates
Input: 2, 2, 3, 7
Print: 2

我不知道我的逻辑是否是绝对的,但不知何故它是有效的,
我用我的代码完成了这个代码:

int arrayLength = 0;
int prev, next;
int sortStatus = 1;

Console.Write("Input array Length: ");
arrayLength = Convert.ToInt32(Console.ReadLine());
int[] ar = new int[arrayLength];

for (int x = 0; x < arrayLength; x++)
{
    Console.Write("Input {0} value: ", (x+1).ToString());
    ar[x] = Convert.ToInt32(Console.ReadLine());
}

for (int x = 0; x < ar.Length-1; x++)
{
    prev = (int)ar[x];
    next = (int)ar[x + 1];

    if (next < prev)
        sortStatus = 0;
    if (next == prev)
        sortStatus = 2;
}

Console.Write(sortStatus.ToString());
Console.Read();

是否可以在LINQ中表达这一点?怎么样?

4 个答案:

答案 0 :(得分:17)

if (ar.SequenceEqual(ar.OrderBy(x => x)))
{
    if (ar.Distinct().Count() == ar.Length)
        return 1;
    else
        return 2;
}
else 
{
    return 0;
}

答案 1 :(得分:5)

纯粹的LINQ替代方案......(仅用于学术兴趣(但可能仍然比接受的答案更快!)

var input = new int[] { 1, 2, 3, 4, 5 };

var output = input.Zip(input.Skip(1), (a, b) => new {a=a, b=b})
                .Aggregate(1, (status, x) => status == 0 ? 0 : ((x.a > x.b ? 0 : (x.a == x.b ? 2 : status))));

答案 2 :(得分:3)

作为一个注释,你表达的非LINQ逻辑有一个缺陷。

if (next < prev) 
    sortStatus = 0; 
if (next == prev) 
    sortStatus = 2; 

您的规则表明数组必须按升序排序,但必须重复才能获得2的输出。但是,{ 1, 9, 7, 7 }的逻辑将返回2。

编写代码的另一种方法可能如下。 (这不是使用LINQ,但这个问题太长了,无法发表评论作为您的问题。)

static int EvaluateArray(int[] array)
{
    int? lastItem = null;
    bool match = false;
    foreach (int item in array)
    {
        if (item < lastItem)
            return 0;
        else if (item == lastItem)
            match = true;

        lastItem = item;
    }

    if (match)
        return 2;

    return 1;
}

在这种方法中,一旦我们有一个小于前一个项目的项目,我们就会提前返回。否则,如果遇到匹配值,我们将设置一个布尔值。在循环结束时,我们知道数组是按升序排序的。唯一剩下的就是检查是否有匹配。

答案 3 :(得分:0)

未测试。

IEnumerable<int> signs = 
  from i in Enumerable.Range(0, ar.Length).Skip(1)
  select ar[i-1].CompareTo(ar[i]);

int result =
  signs.Any(sign => sign < 0) ? 0 :
  signs.All(sign => 0 < sign) ? 1 :
  2;

也未经测试:

int minSign = !ar.Skip(1).Any() ? 1 :
(
  from i in Enumerable.Range(0, ar.Length).Skip(1)
  select ar[i-1].CompareTo(ar[i])
).TakeWhile(x => 0 <= x).Min();

int result =
  minSign < 0 ? 0 :
  0 < minSign ? 1 :
  2;