简体   繁体   English

使用linq避免嵌套循环

[英]Using linq to avoid nested loop

I want to create a method to find the index of two numbers whose sum is target . 我想创建一种方法来查找两个数字的索引,其总和为target

So, I have created this method: 因此,我创建了此方法:

public static int[] TwoSum(int[] nums, int target)
{
    for (var i = 0; i < nums.Length; i++)
    {
        for (var j = 0; j < nums.Length; j++)
        {
            if (j == i) continue;

            if (nums[i] + nums[j] == target)
            {
                return new[] { i, j };
            }
        }
    }
}

Which works fine. 哪个工作正常。 However, I am trying to learn myself some LINQ and can't figure it out. 但是,我正在尝试向自己学习一些LINQ,无法解决。 I looked at various examples, but I always end up stuck because I am using the same array twice. 我查看了各种示例,但由于使用两次相同的数组,所以最终总是陷入困境。 So I don't know what to select and how to access it twice while also making sure it doesn't go through the same indexes twice. 因此,我不知道该选择什么以及如何两次访问它,同时也不确保它不会两次通过相同的索引。

Any help getting a LINQ from the above loops would be appreciated. 从上述循环中获取LINQ的任何帮助将不胜感激。

Sample data: 样本数据:

var nums = new [] { 2, 7, 11, 15 };
var target = 9;

The LINQ equivalent of your loop would be: 循环的LINQ等效项为:

from x in nums.Select((n, i) => new { Number = n, Index = i })
from y in nums.Select((n, i) => new { Number = n, Index = i })
where x.Index != y.Index && x.Number + y.Number == target
select new [] { x.Index, y.Index }

But this requires the creation of anonymous type instance so I would say the loop version is much better and efficient. 但这需要创建匿名类型实例,因此我想说循环版本会更好,更有效。

Here it is as a single LINQ statement, using SelectMany . 这是使用SelectMany的单个LINQ语句。 With LINQ, you have to flip your mind upside down... just type return and then go from there. 使用LINQ,您必须将思维颠倒过来……只需键入return然后从那里开始。

public static int[] TwoSumWithLinq(int[] nums, int target)
{
    return nums.SelectMany
    (
        (m, i) => nums.Select
            (
                (n,j) => new { n, m, i, j }
            )
    )
    .Where
    (
        r => (r.i != r.j) && (r.m + r.n == target)
    )
    .Select
    (
        r => new int[] { r.i, r.j }
    )
    .FirstOrDefault();
}

Link to working example on DotNetFiddle 链接到DotNetFiddle上的工作示例

I would go with the slightly cleaner version: 我会选择比较干净的版本:

public static int[] TwoSum(int[] nums, int target)
{
    return
    (
        from i in Enumerable.Range(0, nums.Length)
        from j in Enumerable.Range(0, nums.Length)
        where i != j && nums[i] + nums[j] == target
        select new [] { i, j }
    ).FirstOrDefault();
 }
public static int[] TwoSum(int[] nums, int target)
{
    int[] indexes = Enumerable.Range(0, nums.Length).ToArray();

    var result =  from i in indexes
                  from j in indexes
                  where i != j && (nums[i] + nums[j]) == target
                  select new []
                  {
                      i,
                      j
                  };

    return result.FirstOrDefault();
}

Please note that the method will return null if there aren't any members in the array that will match the condition (sum of members = target) 请注意,如果数组中没有任何匹配条件的成员,则该方法将返回null (成员总数=目标)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM