通过LINQ查找目标编号是否是数组中两个数字的总和

时间:2010-02-25 05:38:51

标签: c# linq arrays

基本解决方案如下所示:

bool sortTest(int[] numbers, int target)
{
    Array.Sort(numbers);
    for(int i = 0; i < numbers.Length; i++)
    {
       for(int j = numbers.Length-1; j > i; j--)
       {
           if(numbers[i] + numbers[j] == target)
               return true;
       }
    }
    return false;
}

现在我对LINQ很新,但这是我到目前为止写的:

var result = from num in numbers
             where numbers.Contains(target -num)
             select num;
if (result.Count() > 0)
    return true;

return false;

现在我遇到了一个问题,给出了以下例子:
数组:1,2,4,5,8 目标:16

它应该返回false,但它正在捕捉16-8 = 8。那么我怎么去不让它在包含检查中注意到它?或者我可以在查询中每次创建第二个数组,但不包含我正在使用的数字(从而解决问题)?

提前致谢。

3 个答案:

答案 0 :(得分:5)

这是你要找的吗?

var result = from n1 in numbers
             from n2 in numbers
             where n1 != n2 && n1 + n2 == target
             select new { n1, n2 };

[编辑] 这将返回两次匹配,并忽略数组在数组中重复的情况。您无法使用表达式语法处理这些情况,因为您无法访问匹配项的索引,但您可以这样做:

var result = numbers.Select((n1, idx) => 
    new {n1, n2 = numbers.Take(idx).FirstOrDefault(
    n2 => n1 + n2 == target)}).Where(pair => pair.n2 != 0);

只要你的数组中没有任何零。

[进一步思考编辑]

完美的混合解决方案:

var result = from item in numbers.Select((n1, idx) =>
                 new {n1, shortList = numbers.Take(idx)})
             from n2 in item.shortList
             where item.n1 + n2 == target
             select new {n1 = item.n1, n2};

答案 1 :(得分:4)

我一般要解决这个问题,首先要写一个“选择器”。

public static IEnumerable<IEnumerable<T>> Chooser<T>(this IList<T> sequence, int num)
{ ... left as an exercise ... }

选择器的输出是一系列序列。每个子序列的长度为num,由选自原始序列的元素组成。因此,如果您通过{10,30,20,50}作为序列而3作为num,您将获得序列序列:

{10, 30, 20}, {10, 30, 50}, {10, 20, 50}, {30, 20, 50}

结果。

一旦你写了Chooser,问题就变得容易了:

var results = 
  from subsequence in numbers.Chooser(2)
  where subsequence.Sum() == target
  select subsequence;

现在你可以解决其他尺寸的子序列的问题,而不仅仅是对。

编写选择器有点棘手,但它不是很难。

答案 2 :(得分:1)

要改进pdr的回复并解决评论中提到的问题,您可以使用overloaded Select method来比较项目的索引并确保唯一性。

public bool sortTest(int[] numbers, int target)
{
    var indexedInput = numbers.Select((n, i) => new { Number = n, Index = i });

    var result = from x in indexedInput
                 from y in indexedInput
                 where x.Index != y.Index
                 select x.Number + y.Number == target;

    return result.Any(item => item);
}

或点符号:

var result = numbers.Select((n, i) => new { Number = n, Index = i })
                    .SelectMany(
                        x => indexedInput,
                        (x, y) => new { x = x,  y = y })
                    .Where(item => item.x.Index != item.y.Index)
                    .Select(item => item.x.Number + item.y.Number == target);