我的课程类似于此
List<MainCat> AllCat;
public class MainCat
{
public string id { get; set; }
public string name { get; set; }
public List<subcat> subcat { get; set; }
}
public class subcat
{
public string id { get; set; }
public string name { get; set; }
public List<subsubcat> subsubcat { get; set; }
}
public class subsubcat
{
public string id { get; set; }
public string name { get; set; }
}
我想通过 id 获取名称, 例如我知道id是 69
我想得到像这样的输出
MainCat.name&gt; subcat.name&gt; subsubcat.name(如果在subsubcat中找到 69 )
MainCat.name&gt; subcat.name(如果在subcat中找到 69 )
MainCat.name(如果在MainCat中找到 69 )
答案 0 :(得分:1)
如果我已经正确理解了您的要求,那么查询语法就可以解决这个问题:
IEnumerable<string> MyFunc(IEnumerable<MainCat> mainCategories, string idToMatch)
{
return (from main in mainCategories
where main.id == idToMatch
select main.name)
.Concat(from main in mainCategories
from sub in main.subcat
where sub.id == idToMatch
select string.Format("{0} > {1}", main.name, sub.name))
.Concat(from main in mainCategories
from sub in main.subcat
from subsub in sub.subsubcat
where subsub.id == idToMatch
select string.Format("{0} > {1} > {2}", main.name, sub.name, subsub.name));
}
如果您只对第一场比赛感兴趣,可以将其称为
string resultName = MyFunc(AllCat, "69").FirstOrDefault();
因为查询使用延迟执行,所以如果在主类别中找到匹配,这将避免调用更复杂的查询。
也可以将SelectMany
函数与函数调用语法一起使用,但是,它更难以遵循,例如以下是我重新编写第二个.Concat(...)
调用内容的方式,以便说明:
mainCategories.SelectMany(main => main.subcat, (main, sub) => new { Main = main, Sub = sub })
.SelectMany(pair => pair.Sub.subsubcat, (pair, subsub) => new { Main = pair.Main, Sub = pair.Sub, SubSub = subsub})
.Where(triplet => triplet.SubSub.id == idToMatch)
.Select(triplet => string.Format("{0} > {1} > {2}", triplet.Main, triplet.Sub, triplet.SubSub));
据我所知,查询语法在幕后编译成与此类似的内容。
<小时/> 接受回答后更新,我回来再次查看我的代码:
另一种可能性是为所有3个类添加一个接口(或者将它们统一到一个类中,或者根据实际用例从公共基类派生)。
这允许一个可以搜索到任意深度的递归实现(下面是两个不同的基于Linq的实现,具体取决于你是否有一个或其他语法的偏好):
public interface ITreeCat
{
string id { get; }
string name { get; }
IEnumerable<ITreeCat> subcat { get; }
}
// add explicit interface implemetantion to existing 3 classes
// e.g.
// IEnumerable<ITreeCat> ITreeCat.subcat { get { return subsubcat; } }
// IEnumerable<ITreeCat> ITreeCat.subcat { get { return Enumerable.Empty<ITreeCat>(); } }
IEnumerable<string> MyFunc(IEnumerable<ITreeCat> categories, string idToMatch, string prefix = "")
{
return (from cat in categories
where cat.id == idToMatch
select prefix + cat.name)
.Concat(from cat in categories
from recursiveResult in MyFunc(cat.subcat, idToMatch, prefix + cat.name + " > ")
select recursiveResult);
}
IEnumerable<string> MyFunc2(IEnumerable<ITreeCat> categories, string idToMatch, string prefix = "")
{
return categories.Where(cat => cat.id == idToMatch)
.Select(cat => prefix + cat.name)
.Concat(categories.SelectMany(cat => MyFunc2(cat.subcat, idToMatch, prefix + cat.name + " > ")));
}
这样做的好处是,如果稍后添加subsubsubcat等,它将继续工作。
以上所有代码示例都使用广度优先搜索,并且每次深入一级时都会重复枚举“父级”类别。
在某些应用程序中,深度优先搜索可能是更好的选择,因为每个列表仅枚举一次,在这种情况下,使用foreach
而不是Linq更容易。同样,递归版本比具有不同类的3个嵌套循环更简洁:
IEnumerable<string> MyFuncDepthFirst(IEnumerable<ITreeCat> categories, string idToMatch)
{
foreach(var cat in categories)
{
if (cat.id == idToMatch)
yield return cat.name;
foreach (var subResult in MyFuncDepthFirst(cat.subcat, idToMatch))
yield return string.Format("{0} > {1}", cat.name, subResult);
}
}
这仍假设可能发生多次匹配。如果我们刚刚在第一个匹配之后,则根本不需要使用迭代器块,并且可以修改上述函数以返回一个简单的字符串:
string FirstMatchingIdDepthFirst(IEnumerable<ITreeCat> categories, string idToMatch)
{
foreach(var cat in categories)
{
if (cat.id == idToMatch)
return cat.name;
string subResult = FirstMatchingIdDepthFirst(cat.subcat, idToMatch);
if(subResult != null)
return string.Format("{0} > {1}", cat.name, subResult);
}
return null;
}
答案 1 :(得分:0)
var list = this.AllCat.Where(t=>t.subcat.Any(s=> subsubcat.contains(s));
答案 2 :(得分:0)
您可以选择以下方法
public static Type Find(string id, MainCat m)
{
if (m.id.Equals(id))
{
return m.GetType();
}
if (m.subcat.Any(a => a.id.Equals(id)))
{
return typeof(subcat);
}
if (m.subcat.Any(a => a.subsubcat.Any(b => b.id.Equals(id))))
{
return typeof(subsubcat);
}
return null;
}
并执行搜索。找到要点,https://gist.github.com/IshamMohamed/33d75064789d77d88404b8ffc9a17e94
通过这种方式,您可以增加内部列表的数量(例如:subsubsubcat
)