使用linq的数组索引除外

时间:2014-11-06 12:44:15

标签: c# .net linq

我有以下两个列表

List<String> list1 = new List<String>();
list1.Add("one");
list1.Add("two");
list1.Add("three");
list1.Add("four");
list1.Add("five");

List<String> list2= new List<String>();
list2.Add("one");
list2.Add("two");
list2.Add("three");

IEnumerable<int> indexOfUnwantedColumns;
indexOfUnwantedColumns = list1.Except(list2)
                              .Select((p, i) => new { Item = p, Index = i })
                              .Select(p => p.Index);

正如预期的那样,这将给出新列表中的两个项目的索引(0和1)。我希望能够从原始列表(3和4)中获取索引值

任何帮助将不胜感激

2 个答案:

答案 0 :(得分:0)

这是一个简单的方法:

IEnumerable<int> indexOfUnwantedColumns = list1
  .Select((str, index) => new {str, index} )
  .Where(x => !list2.Contains(x.str))
  .Select(x => x.index);

对大型序列采用更有效的方法是使用Enumerable.Join(&#34;左外连接&#34;):

var l1Cols = list1.Select((str, index) => new {str, index} );
var l2Cols = list2.Select((str, index) => new {str, index} );
IEnumerable<int> indexOfUnwantedColumns = 
            from c1 in l1Cols
            join c2 in l2Cols on c1.str equals c2.str into gj
            from outerJoin in gj.DefaultIfEmpty()
            where outerJoin == null
            select c1.index;

答案 1 :(得分:0)

主要思想是在过滤之前捕获原始索引,然后检查list2是否包含每个项目。为了能够有效地执行这些查找(每个查询的O(1)聚合时间),您应该使用一个哈希集:

var hashset = new HashSet<string>(list2);
var unwantedColIndexes = list1
    .Select((item, idx) => new { item, idx })  // capture the original index
    .Where(i => !hashset.Contains(i.item))     // filter using the hashset
    .Select(i => i.idx)                        // get the index only
    .ToList();