我有一个对象类型A
的集合。我想知道我是否可以创建另一个集合,包括A
的子集,例如if A[i].Something == 'a' && A[i+1].Something == 'b'
,然后将其添加到新集合中。
新集合将是KeyValue
对的列表,(Key = A[i], Value = A[i+1])
我想用lambda exp完成这个。有人可以指导我吗?
答案 0 :(得分:5)
由于标准 Linq 不支持 Lead
(Lag
)方法(如果您坚持,请查看More Linq在Linq-like解决方案上),我建议实现一个简单的生成器:
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();
答案 1 :(得分:2)
获取键/值对的另一种方法是使用除第一项之外的所有项目对集合进行压缩。理论上应该在任何保留顺序的可枚举上工作。如果'coll'是您的来源:
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")
答案 2 :(得分: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);
答案 3 :(得分: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"
);
答案 4 :(得分: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);
}
}