查找集合中每个不同邮政编码的最后一次出现的索引

时间:2014-07-31 20:27:38

标签: c# linq collections

给出一个课程:

public class Data {
    public string name { get; set; }
    public string gender { get; set; }
    public string zipcode { get; set; }
}

如下面的列表中有三个不同的zipcode:["21112" ,"21046", "21075"]

var items = new List<Data> {
    new Data { name = "bob", gender = "male", zipcode = "21112" }
    new Data { name = "sarah", gender = "female", zipcode = "21046" }
    new Data { name = "steven", gender = "male", zipcode = "21112" }
    new Data { name = "joe", gender = "male", zipcode = "21046" }
    new Data { name = "karen", gender = "female", zipcode = "21075" }
}

如果我按邮政编码排序列表,如何找到每个不同邮政编码最后一次出现的索引(集合中项目的从零开始的索引):

items.OrderBy(i => i.zipcode)??

我需要索引,因为我需要在每个索引后插入一个项目。我得到了Data的集合,我需要在返回之前对其进行修改。

3 个答案:

答案 0 :(得分:2)

你可以这样做:

items.GroupBy(i => i.ZipCode).Select(group => items.IndexOf(group.Last()));

答案 1 :(得分:2)

假设您需要邮政编码和索引,您可以使用匿名类型或元组。以下是前者的一个例子:

items.GroupBy(i => i.zipcode).Select(list => new 
{ 
    ZipCode = list.Last().zipcode, 
    Index = items.IndexOf(list.Last()) 
});

如果您愿意,可以使用查询理解语法并使用let子句指定最后一个元素,以便LINQ不可能遍历列表两次

var insertions = from item in items
                 group item by item.zipcode into grouped
                 let last = grouped.Last()
                 select new 
                 {
                     ZipCode = last.zipcode,
                     Index = items.IndexOf(last)
                  };

由于您需要使用索引更新原始列表,您可能需要在更新原始表之前实现可枚举的插入,否则您将发生异常。为此,只需在子句的末尾添加.ToList()。

答案 2 :(得分:2)

这并不像其他答案那样优雅,也可能效率不高,但无论如何都可能有所帮助,所以在这里:

List<T>.OrderBy()返回一个IOrderedEnumerable,可以像其他任何IEnumerable一样调用.ToList()。所以你可以这样做:

List<Data> orderedList = items.OrderBy(i => i.zipcode).ToList(); //outputs a plain list in the sorted order
List<string> distinctZipCodes = (from i in orderedList select i.zipcode).Distinct(); //get a list of distinct zip codes
foreach(string s in DistinctZipCodes)
{
     int index = orderedList.FindLastIndex((e)=> {return (e.zipcode== s);}); //get last index of each zip
     //do something with index
}