【问题标题】:Finding if a target number is the sum of two numbers in an array via LINQ通过LINQ查找目标数字是否是数组中两个数字的总和
【发布时间】:2010-02-25 05:38:51
【问题描述】:

基本解决方案如下所示:

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。那么我该如何不让它在包含检查中注意到自己呢?或者我可以每次在不包含我正在使用的数字的查询中创建第二个数组(从而解决问题)?

提前致谢。

【问题讨论】:

    标签: c# linq arrays


    【解决方案1】:

    这就是你要找的吗?

    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
    • 一件事:如果数组包含两个相等的数字并且加起来等于目标怎么办?例如:数组包含 2 个 8,目标是 16。除此之外,您的陈述很棒,对我帮助很大。
    • 是的,它还会返回任何匹配对两次:即。 4 + 8 = 12; 8 + 4 = 12。我只是想找出一个更好的答案。
    【解决方案2】:

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

    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}
    

    结果。

    一旦你写好了选择器,问题就变得简单了:

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

    现在您可以解决其他大小的子序列的问题,而不仅仅是对。

    编写选择器有点棘手,但难。

    【讨论】:

      【解决方案3】:

      为了改进 pdr 的回复并解决 cmets 中提到的问题,您可以使用 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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-31
        • 1970-01-01
        • 1970-01-01
        • 2015-01-16
        • 2022-01-12
        • 1970-01-01
        • 2014-06-27
        • 1970-01-01
        相关资源
        最近更新 更多