我有两个列表double list1和list2。我正在比较两个列表,并对list2中list1匹配项目的项目索引感兴趣。我在linq表达式下面使用:
List<double> list1 = new List<double> () {1.0 , 2.0 , 5.0 , 7.0 , 8.0} ;
List<double> list2 = new List<double> () {2.0 ,7.0 ,9.0} ;
List<int> kk= new List <int> () ;
list2.ForEach (xx => kk.Add (list1.Select((v, i) => new { v, i }).Where(x => x.v == xx).Select(x => x.i).FirstOrDefault ()));
如果list1中的项目不存在于list1中,那么我在上面的语句中有一个问题,那么我得到0值作为回报,这个零值在列表kk中添加。如何在列表kk中添加0值来避免。
答案 0 :(得分:2)
您遇到问题,因为如果未找到匹配项,则选择默认值(零)。我建议你使用join - 它也比迭代外部序列中每个项目的内部序列更快(O(N)而不是搜索:
from x in list1.Select((l1,i) => new { l1, i })
join l2 in list2 on x.l1 equals l2
select x.i
或lambda语法:
list1.Select((l1,i) => new { l1, i })
.Join(list2, x => x.l1, l2 => l2, (x, l2) => x.i);
内部连接创建内部序列的查找(在这种情况下为list2) - 在内部序列上进行单次迭代。然后我们需要在外部序列上进行一次迭代,以从查找中获取连接的内部项。类似的东西:
public IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner TResult> resultSelector)
{
var lookup = inner.ToLookup(innerKeySelector); // iterate over list2
foreach(var outerItem in outer)
{
var joined = lookup[outerKeySelector(outerItem)]; // quick search, O(1)
if (!joined.Any())
continue; // go to next outer item if no matches exist
foreach(var joindeItem in joined) // iterate over matches
yield return resultSelector(outerItem, joinedItem); // return index
}
}
实际实施稍微优化一点,但核心理念是一样的。
答案 1 :(得分:0)
您的大多数代码都忙于查找列表中给定元素的索引。 List<T>
已经有一个方法IndexOf
,如果找到该项,则返回索引;如果不找到,则返回-1
。
如果您不关心性能(运行时为list1.Count * list2.Count
),您可以使用:
kk = list2.Select(xx => list1.IndexOf(xx)).Where(i => (i >= 0)).ToList();
如果效果很重要,则需要将list1
转换为Dictionary<double, int>
,将运行时间缩短为list1.Count + list2.Count
。