在知道每个Select / SelectMany结果的同时在Linq中转换序列

时间:2013-10-11 14:19:41

标签: c# linq

这是我的问题。我有一个特定的列表,为了简单起见,我将其作为int[]呈现。

int[] a = {1,2,3,4,5};

假设我需要转换此列表中的每个项目,但根据具体情况,我可能会返回一个int或一组int。

例如,如果值奇数,则需要返回{v};如果值偶数,则需要返回{v,v+1}。我做到了这一点:

int[] b = a.SelectMany(v => v % 2 == 0 ? new int[] { v, v+1 } : new int[] { v })
           .ToArray();

所以如果我运行它,我会得到预期的响应:

{1,2,3,3,4,5,5}

看到我有重复的数字,对吗? 35。我不想要那些重复的数字。现在,您可以告诉我,我可以在处理数组后调用.Distinct()

这就是问题所在。 SelectMany子句相当复杂(我只是编写了一个更简单的例子),如果它已经存在于列表中,我肯定不想处理3

我可以检查原始列表中是否存在3。但如果我在3条款中得到SelectMany,我不想再得到它。例如,如果我有这个清单:

int[] a = {1,2,3,4,5,2};

我会得到这个:

{1,2,3,3,4,5,5,2,3}

因此,最后再次返回v(我的原始值)和v+1。这样你就可以更好地理解v+1代表我想要避免的一些处理。

总结一下,这就是我想要的:

  1. 我有一个对象列表。的(检查)
  2. 我需要过滤它们,根据结果,我可能需要返回多个对象。 (检查,使用SelectMany
  3. 我需要它们与众不同,但我不能在这个过程结束时这样做。如果{v}已存在,我应该只返回{v+1}。的(没有线索...)
  4. 我想到的一件事是编写一个可能符合我需求的自定义SelectMany,但我想确定没有内置的方法来执行此操作。

    编辑:我相信我可能会因为我的榜样误导你们。我知道如何确定v+1是否在列表中。要清楚,我有一个对象有2个int属性,Id和IdParent。我需要“回报”所有对象他们的父母。但我只有ParentId,它来自对象本身。我能够知道列表中是否有v+1,因为我可以检查其中的任何对象是否与我正在检查的ParentId具有相同的ID。

    答案:我最终使用了Aggregate,这可以用来做我正在寻找的内容。

4 个答案:

答案 0 :(得分:3)

这个简单的循环与HashSet<int>有帮助吗?

int[] a = {1,2,3,4,5,2};
var aLookupList = new HashSet<int>();
foreach (int i in a)
{
    bool isEven = i % 2 == 0;
    if (isEven)
    {
        aLookupList.Add(i);
        aLookupList.Add(i + 1);
    }
    else
    {
        aLookupList.Add(i);
    }
}
var result = aLookupList.ToArray();

答案 1 :(得分:1)

使用Aggregate方法怎么样?您不会处理列表中已有的数字,也不会处理原始列表中的数字或应用的数字(v + 1)

 int[] v = { 1, 2, 3, 4, 5, 2 };

 var result = v.Aggregate(new List<int>(),
   (acc, next) =>
   {
     if (!acc.Contains(next))
       return (next % 2 == 0) ? acc.Concat(new int[] { next, next + 1 }).ToList()
                              : acc.Concat(new int[] { next }).ToList();
     else
       return acc;
   }).ToArray();

答案 2 :(得分:0)

var existing = new HashSet<int>(a);

var result = existing
    .Where(v => v % 2 == 0 && !existing.Contains(v + 1))
    .Select(v => v + 1)
    .Concat(existing)
    .ToArray();

答案 3 :(得分:0)

据我所知,你有这样的意见:

int[] a = {1,2,3,4,5};

输出也应为{1,2,3,4,5},因为您不需要如您所述的重复数字。 因为您使用array作为输入,所以您可以尝试以下代码:

var output = a.SelectMany((x,i)=> x % 2 == 0 ? new []{x,x+1} : 
                                  i > 0 && a[i-1]==x-1 ? new int[]{} : new []{x});
//if the input is {1,2,4,5}
//The output is also {1,2,3,4,5}