使用LINQ获取上次迭代的参数

时间:2009-11-16 07:38:22

标签: c# linq linq-to-objects

如何在没有迭代的情况下使用LINQ执行此操作?

 string[] flatSource = {"region1", "subregion1", 
                        "region2", "sub1", "sub2", 
                        "region3", "sub1", "sub2"};

 string previousRegion = "";
 foreach (var item in flatSource)
 {
    if (SomeRegionDictionary.Contains(item))
       previousRegion = item;  //This is what I can't figure out 
    else
       yield return new SubregionWithRegion{Region = previousRegion, SubRegion = item};
 }

4 个答案:

答案 0 :(得分:3)

您当前的解决方案很好; LINQ不是这种有状态查询的理想选择。 这是一个纯LINQ解决方案;它并不理想,因为它有点神秘具有二次复杂性,但功能相同:

return flatSource.Select((item, index) => 
                     new SubregionWithRegion
                     {
                       Region = flatSource.Take(index + 1)
                                          .LastOrDefault(SomeRegionDictionary.ContainsKey) ?? "",
                       SubRegion = item
                     })
                  .Where(srwr => !SomeRegionDictionary.ContainsKey(srwr.SubRegion));

循环的有状态性质由Take + LastOrDefault个查询处理,棘手的else条件由最终的Where子句处理。

答案 1 :(得分:2)

似乎我没有仔细阅读这个问题。所以下面的扩展可能有用,但不是这个问题。

public static class IEnumerableOfTExtensions
{
    public static T Before<T>(this IEnumerable<T> source, Func<T, bool> condition)
    {
        if (source == null)
            throw new ArgumentNullException("source");

        if (condition == null)
            throw new ArgumentNullException("condition");

        using (var e = source.GetEnumerator())
        {
            var first = true;
            var before = default(T);

            while (e.MoveNext())
            {
                if (condition(e.Current))
                {
                    if (first)
                        throw new ArgumentOutOfRangeException("condition", "The first element corresponds to the condition.");

                    return before;
                }

                first = false;
                before = e.Current;
            }
        }

        throw new ArgumentOutOfRangeException("condition", "No element corresponds to the condition.");
    }
}

答案 2 :(得分:1)

也许你会发现Enumerable.Aggregate方法很有用。

答案 3 :(得分:1)

你可以在一个声明中使用Zip in Net 4.0:

return
 flatSource.Where(i=>SomeRegionDictionary.Contains(i)).Zip(arr.Skip(1),
  (first, second) => new SubregionWithRegion{Region = first, SubRegion = second});

如果您没有Net 4.0,则可以使用此实现:Zip Me Up