滚动列表,直到找到具有相应 ID 的对象 - C#
scroll the list until you find the object with the corresponding id - C#
我有一个这样的列表(已经用 visual studio 调试器打开):
正如你所看到的列表是由其他相同类型列表的对象组成的,我的需要是运行遍历所有子项,而不考虑索引并验证FID 该对象与 UI 传递的对象相同。一旦找到 return 相同对象的匹配服务器。
我可以试试这个来测试,
但考虑到我只有顶级项目,索引为 0 的项目不会全部流入:
AttachmentFolders childWithId17 = ApplicationContext.Instance.companyList[0].AttachmentFolders.SelectMany(parent => parent.AttachmentFolder)
.FirstOrDefault(child => child.FID == "835A09A2-9D60-46CC-A2BE-D4CBC4C81860");
换张图更好理解
事实上,我得到了一个包含很多元素的列表,应该滚动它,即使是以响应的方式也能够return对应于 AttachmentFolders [=32= 的对象]FID .
class 结构:
public class AttachmentFolders
{
public int id { get; set; }
public String FID { get; set; }
public String Name { get; set; }
public String CPID { get; set; }
public String ParentFID { get; set; }
public List<Attachment> Attachments { get; set; }
public List<AttachmentFolders> AttachmentFolder { get; set; }
}
public class Attachment
{
public int id { get; set; }
public String ATID { get; set; }
public String Name { get; set; }
public String CreatorID { get; set; }
public String FID { get; set; }
public String Extension { get; set; }
public String Description { get; set; }
public int Status { get; set; }
public String CPID { get; set; }
public int FileSize { get; set; }
public DateTime CreationDate { get; set; }
public DateTime ModifiedDate { get; set; }
public int AttachmentType { get; set; }
public int ValidityType { get; set; }
public List<Revisions> Revisions { get; set; }
public String AWID { get; set; }
public String WAID { get; set; }
public String WatermarkPositions { get; set; }
public Boolean Serveroffline { get; set; }
public Boolean IsFavourite { get; set; }
public DateTime LastOpenDate { get; set; }
public int Priority { get; set; }
public String CreatorFirstName { get; set; }
public String CreatorLastName { get; set; }
public String ModifiedByFirstName { get; set; }
public String ModifiedByLastName { get; set; }
public String[] Capabilities { get; set; }
}
谢谢大家
这是一个典型的递归案例。您可以尝试搜索扁平化的树结构,如 this or this 答案中所做的那样。
如果您遇到此解决方案性能缓慢的问题,我会考虑创建一个助手 Dictionary<string, AttachmentFolders>
对象,该对象将保存所有(子)文件夹引用以便快速访问,例如
IEnumerable<AttachmentFolders> Flatten(AttachmentFolders f)
{
var fs = new[] { f };
return f.Children == null? fs : fs.Concat(f.Children.SelectMany(Flatten));
}
Dictionary<string, AttachmentFolders> GenerateCache(AttachmentFolders firstFolder)
{
return Flatten(firstFolder).ToDictionary(f => f.FID, f => f);
}
然后,开始时一次性:
Dictionary<string, AttachmentFolders> Cache = GenerateCache(firstFolder);
并且每次提出请求时:
if(Cache.ContainsKey(fid)) return Cache[fid];
else throw new Exception("Handle not found FID here");
您可以像 Marc 的回答中那样写 SelectDeep
扩展名:Expressing recursion in LINQ
然后在您的代码中使用它而不是 SelectMany
:
AttachmentFolders child = companyList[0].AttachmentFolders
.SelectDeep(parent => parent.AttachmentFolder)
.FirstOrDefault(child => child.FID == "835A09A2-9D60-46CC-A2BE-D4CBC4C81860");
SelectDeep
方法如下所示:
public static class EnumerableExtensions
{
public static IEnumerable<T> SelectDeep<T>(
this IEnumerable<T> source, Func<T, IEnumerable<T>> selector) {
foreach (T item in source) {
yield return item;
foreach (T subItem in SelectDeep(selector(item), selector)) {
yield return subItem;
}
}
}
}
我有一个这样的列表(已经用 visual studio 调试器打开):
正如你所看到的列表是由其他相同类型列表的对象组成的,我的需要是运行遍历所有子项,而不考虑索引并验证FID 该对象与 UI 传递的对象相同。一旦找到 return 相同对象的匹配服务器。
我可以试试这个来测试, 但考虑到我只有顶级项目,索引为 0 的项目不会全部流入:
AttachmentFolders childWithId17 = ApplicationContext.Instance.companyList[0].AttachmentFolders.SelectMany(parent => parent.AttachmentFolder)
.FirstOrDefault(child => child.FID == "835A09A2-9D60-46CC-A2BE-D4CBC4C81860");
换张图更好理解
事实上,我得到了一个包含很多元素的列表,应该滚动它,即使是以响应的方式也能够return对应于 AttachmentFolders [=32= 的对象]FID .
class 结构:
public class AttachmentFolders
{
public int id { get; set; }
public String FID { get; set; }
public String Name { get; set; }
public String CPID { get; set; }
public String ParentFID { get; set; }
public List<Attachment> Attachments { get; set; }
public List<AttachmentFolders> AttachmentFolder { get; set; }
}
public class Attachment
{
public int id { get; set; }
public String ATID { get; set; }
public String Name { get; set; }
public String CreatorID { get; set; }
public String FID { get; set; }
public String Extension { get; set; }
public String Description { get; set; }
public int Status { get; set; }
public String CPID { get; set; }
public int FileSize { get; set; }
public DateTime CreationDate { get; set; }
public DateTime ModifiedDate { get; set; }
public int AttachmentType { get; set; }
public int ValidityType { get; set; }
public List<Revisions> Revisions { get; set; }
public String AWID { get; set; }
public String WAID { get; set; }
public String WatermarkPositions { get; set; }
public Boolean Serveroffline { get; set; }
public Boolean IsFavourite { get; set; }
public DateTime LastOpenDate { get; set; }
public int Priority { get; set; }
public String CreatorFirstName { get; set; }
public String CreatorLastName { get; set; }
public String ModifiedByFirstName { get; set; }
public String ModifiedByLastName { get; set; }
public String[] Capabilities { get; set; }
}
谢谢大家
这是一个典型的递归案例。您可以尝试搜索扁平化的树结构,如 this or this 答案中所做的那样。
如果您遇到此解决方案性能缓慢的问题,我会考虑创建一个助手 Dictionary<string, AttachmentFolders>
对象,该对象将保存所有(子)文件夹引用以便快速访问,例如
IEnumerable<AttachmentFolders> Flatten(AttachmentFolders f)
{
var fs = new[] { f };
return f.Children == null? fs : fs.Concat(f.Children.SelectMany(Flatten));
}
Dictionary<string, AttachmentFolders> GenerateCache(AttachmentFolders firstFolder)
{
return Flatten(firstFolder).ToDictionary(f => f.FID, f => f);
}
然后,开始时一次性:
Dictionary<string, AttachmentFolders> Cache = GenerateCache(firstFolder);
并且每次提出请求时:
if(Cache.ContainsKey(fid)) return Cache[fid];
else throw new Exception("Handle not found FID here");
您可以像 Marc 的回答中那样写 SelectDeep
扩展名:Expressing recursion in LINQ
然后在您的代码中使用它而不是 SelectMany
:
AttachmentFolders child = companyList[0].AttachmentFolders
.SelectDeep(parent => parent.AttachmentFolder)
.FirstOrDefault(child => child.FID == "835A09A2-9D60-46CC-A2BE-D4CBC4C81860");
SelectDeep
方法如下所示:
public static class EnumerableExtensions
{
public static IEnumerable<T> SelectDeep<T>(
this IEnumerable<T> source, Func<T, IEnumerable<T>> selector) {
foreach (T item in source) {
yield return item;
foreach (T subItem in SelectDeep(selector(item), selector)) {
yield return subItem;
}
}
}
}