2017-06-21 91 views
-1

我有一个对象类型集合A。我想知道是否可以创建另一个集合,包括子集A,如if A[i].Something == 'a' && A[i+1].Something == 'b',然后将其添加到新集合中。Linq列表帮助

新系列将是KeyValue双列表,使得(Key = A[i], Value = A[i+1])

我想做到这一点使用lambda进出口。有人可以指导我吗?

回答

4

由于标准的LINQ不支持LeadLag)方法(看看More Linq如果你坚持的LINQ样的解决方案),我建议实施一个简单的发电机:

private static IEnumerable<KeyValue<MyClass, MyClass>> MakePairs(
    IEnumerable<MyClass> source) { 

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

    MyClass prior = default(MyClass); 
    bool first = true; 

    foreach (var current in source) { 
    if (first) { 
     prior = current; 
     first = false; 

     continue; 
    } 

    if (prior != null && current != null && 
     prior.Something == "A" && current.Something == "B") //TODO: put right condition 
     yield return new KeyValue(prior, current); 

    prior = current; 
    } 
} 

... 

IEnumerable<MyClass> source = ... 

var result = MakePairs(source).ToList(); 
+0

您对'prior = source.FirstOrDefault();'然后是'foreach(source.skip(1)中的var current)'有什么看法?这将使'if'多余 – Default

+0

@默认:在source.FirstOrDefault()的情况下,然后在foreach中扫描集合*两次*(即使第一次扫描仅为一个项目)。这可能是一个*问题*如果1.收集开放是昂贵的*(例如,我们有一个文件,RDBMS查询等)2.如果集合是可变的(比如,某人在'FirstOrDefault()'和'foreach')。当收集的来源*未知*,扫描一次* –

0

您可以使用Select,它有一个重载获取索引,在这种情况下可用于检索列表中的下一个项目。

var newCollection = collection.Select 
           ((a, i) => new 
            { A = a 
            , NextA = (i + 1) < collection.Length ? collection[i + 1] : null 
            } 
           ); 

从那里你可以写谓词你想:

var filteredCollection = newCollection.Where 
             (x => x.A.Something == "a" 
              && x.NextA?.Something == "b" 
             ); 
1

将这项工作?

IEnumerable<string> list; 
IEnumerable<string> list2 = list.Skip(1); 

string test1 = "a"; 
string test2 = "b"; 

var result = list 
    .Zip(list.Skip(1), 
     (x, y) => Tuple.Create(x, y)) 
    .Where(r => r.Item1 == test1 && r.Item2 == test2) 
    .ToDictionary(r => r.Item1, 
       r => r.Item2); 
1

另一种获取键/值对的方法是使用除第一个以外的所有项目压缩集合。理论上应该处理任何保留顺序的枚举。如果 '科尔' 是源:

coll.Zip(coll.Skip(1), (a1,a2) => new {Key = a1.Something, Value = a2.Something}) 

要为值 'a' 和 'B' 仅得到:

coll.Zip(coll.Skip(1), (a1,a2) => new {Key = a1.Something, Value = a2.Something}) 
     .Where(kv=>kv.Key == "a" && kv.Value == "b") 
0

OP具有收藏,所以我开始了一个ICollection的:

public static IEnumerable<KeyValuePair<A, A>> KeyValueSelecting(ICollection<A> source) { 
     if (null == source) { throw new ArgumentNullException(nameof(source)); } 
     for (var i = 0; i < source.Count - 1; i++) { 
      var firstElement = source.ElementAtOrDefault(i); 
      if (firstElement?.Something != "A") { yield break; } 
      var seceondElement = source.ElementAtOrDefault(i + 1); 
      if (seceondElement?.Something != "B") { yield break; } 
      yield return new KeyValuePair<A, A>(firstElement, seceondElement); 
     } 
    }