我有一个存储在List中的数据,它是对象列表。
我需要遍历每个内部列表并检查对象是否满足条件,然后将其存储在其他List中。
public class Data //class that actually holds data
{
public string DataPart;
public string Category;
public Data (string dataPart, string category)
{
this.DataPart = dataPart;
this.Category = category;
}
}
存储数据的数据结构如下:
Dictionary<int, List<Data>>
显示我当前解决方案的示例代码:
Dictionary<int, List<Data>> dataTbl = new Dictionary<int, List<Data>>();
//initializing the data structure
List<Data> lst1 = new List<Data>();
lst1.Add(new Data("data1OfLst1", "cat1"));
lst1.Add(new Data("data2OfLst1", "cat2"));
lst1.Add(new Data("data3Oflst1", "cat3"));
dataTbl.Add(1, lst1);
List<Data> lst2 = new List<Data>();
lst2.Add(new Data("data1OfLst2", "cat1"));
lst2.Add(new Data("data2OfLst2", "cat2"));
lst2.Add(new Data("data3Oflst2", "cat3"));
dataTbl.Add(2, lst2);
List<Data> cat1Data = new List<Data>();
foreach(List<Data> datList in dataTbl.Values)
{
if(datList.Any( x => x.Category == "cat1"))
cat1Data.Add(datList.Where(x => x.Category == "cat1").FirstOrDefault());
}
但是,词典中的记录数量和每个记录List
中的元素数量都是一个很大的数字。因此,我正在寻找更好的解决方案。
请注意,Dictionary
中的某些记录可能不包含满足条件的任何此类数据(此处为"cat1"
检查)。最终列表不应包含null
值
编辑:
一般假设(不是顽固的验证)内部列表中应该只有一个(或没有)特定类别的条目,因此不会有包含多个{{1的对象的内部列表}}
答案 0 :(得分:3)
正如我在评论中已经说过的那样,只要您没有使用分析器指示如果您甚至遇到性能问题,那么您就不会为更快的代码而烦恼strong> if so, if 这是由您的代码或其他您不想到的代码引起的。你看:有很多if。
除此之外,我还有一些更智能的代码,如果有的话,它会更快,但更容易阅读和维护,这应该是你的主要目标,一切否则只是寻找纳秒。
List<Data> cat1Data = new List<Data>();
foreach(List<Data> datList in dataTbl.Values)
{
var el = datList.FirstOrDefault(x => x.Category == "cat1");
if(el != null)
cat1Data.Add(el);
}
FirstOrDefault
将返回默认值(null
表示引用类型,结构类型表示结构默认值)。实际上你是两次检查同一件事。
因此,您无需检查当前列表中是否存在满足条件的元素,然后再次选择此元素。而是直接搜索它并在找到时添加它。
答案 1 :(得分:2)
我建议只在索引除了位置放置之外还有特殊含义时才使用Dictionary。在您的情况下,您可以创建列表对象列表。
public class MainClass
{
public int Id { get; set; }
public List<Data> Data { get; set; }
}
然后用
替换你的代码 MainClass dataTbl = new MainClass();
List<Data> lst1 = new List<Data>();
lst1.Add(new Data("data1OfLst1", "cat1"));
lst1.Add(new Data("data2OfLst1", "cat2"));
lst1.Add(new Data("data3Oflst1", "cat3"));
dataTbl.Id = 1;
dataTbl.Data = lst1;
List<Data> lst2 = new List<Data>();
lst2.Add(new Data("data1OfLst2", "cat1"));
lst2.Add(new Data("data2OfLst2", "cat2"));
lst2.Add(new Data("data3Oflst2", "cat3"));
dataTbl.Id = 2;
dataTbl.Data = lst2;
List<Data> cat1Data = new List<Data>();
cat1Data = dataTbl.Data.Where(i => i.Category.Contains("cat1")).ToList();
包含将确保您的类别数据仅为“cat1”,并且不包含任何空值。
如果您遇到任何问题,请尝试告诉我。
答案 2 :(得分:1)
您可以这样做,并使用cat1
var list = dictionary.Values // To get just the List<Data>s
.SelectMany(x => x) // Flatten
.Where(x => x.Category == "cat1")
.ToList(); // Listify
或
var list = dictionary.SelectMany(x => x.Value) // Flatten
.Where(x => x.Category == "cat1")
.ToList(); // Listify
性能尝试并行linq,这使用多线程但建议比较没有并行性能并使用它
var list = dictionary.Values.AsParallel() // To get just the List<Data>s
.SelectMany(x => x) // Flatten
.Where(x => x.Category == "cat1")
.ToList(); // Listify
注意:如果您真的关心性能,请使用For循环,删除您尝试过的所有linq代码,只使用forloop
答案 3 :(得分:1)
您可以先查询集合而不进行展平,然后删除最后由FirstOrDefault
引起的任何空值:
dataTbl.Values
.Select(x => x.FirstOrDefault(y => y.Category == "cat1"))
.Where(x=>x != null);
答案 4 :(得分:0)
为什么要在循环内检查两次条件?这就像做同样的事情3次。只需根据条件直接选择您的列表即可。无需循环,无需先进行检查:
List<Data> cat1Data = dataTbl.Values
.SelectMany(x => x)
.Where(x => x.Category == "cat1")
.ToList();
正如HenkHolterman所说,它也可以这样写:
List<Data> cat1Data = dataTbl.SelectMany(x => x.Value)
.Where(x => x.Category == "cat1")
.ToList();
结果相同,但性能可能略有不同。