我正在使用名为SDMX的XML标准。它相当复杂,但我会尽可能地缩短它。我收到一个名为CategoryScheme
的对象。此对象可以包含多个Category
,每个Category
可以包含更多Category
,依此类推,链可以是无限的。每个Category
都有一个唯一的ID。
通常每个Category
都包含很多类别。与此对象一起,我收到一个数组,其中包含指示特定Category
嵌套位置的ID列表,然后我收到该类别的ID。
我需要做的是创建一个维护Category
对象层次结构的对象,但每个Category
必须只有 一个孩子,那个孩子必须是一个导致特定Category
的树的。
所以我有一个想法,但为了做到这一点,我应该在一个周期内生成 LINQ查询,我不知道如何做到这一点。有关我想尝试的更多信息,请在代码
我们来看看代码:
public void RemoveCategory(ArtefactIdentity ArtIdentity, string CategoryID, string CategoryTree)
{
try
{
WSModel wsModel = new WSModel();
// Prepare Art Identity and Array
ArtIdentity.Version = ArtIdentity.Version.Replace("_", ".");
var CatTree = JArray.Parse(CategoryTree).Reverse();
// Get Category Scheme
ISdmxObjects SdmxObj = wsModel.GetCategoryScheme(ArtIdentity, false, false);
ICategorySchemeMutableObject CatSchemeObj = SdmxObj.CategorySchemes.FirstOrDefault().MutableInstance;
foreach (var Cat in CatTree)
{
// The cycle should work like this.
// At every iteration it must delete all the elements except the correct one
// and on the next iteration it must delete all the elements of the previously selected element
// At the end, I need to have the CatSchemeObj full of the all chains of categories.
// Iteration 1...
//CatSchemeObj.Items.ToList().RemoveAll(x => x.Id != Cat.ToString());
// Iteration 2...
//CatSchemeObj.Items.ToList().SingleOrDefault().Items.ToList().RemoveAll(x => x.Id != Cat.ToString());
// Iteration 3...
//CatSchemeObj.Items.ToList().SingleOrDefault().Items.ToList().SingleOrDefault().Items.ToList().RemoveAll(x => x.Id != Cat.ToString());
// Etc...
}
}
catch (Exception ex)
{
throw ex;
}
}
感谢您的帮助。
答案 0 :(得分:1)
所以,正如我在评论中已经说过的,构建递归函数应该可以解决问题。如果您是新手,可以在C#here中找到有关递归的一些基本信息。
该方法可能如下所示:
private void DeleteRecursively(int currentRecursionLevel, string[] catTree, ICategorySchemeMutableObject catSchemeObj)
{
catSchemeObj.Items.ToList().RemoveAll(x => x.Id != catTree[currentRecursionLevel].ToString());
var leftoverObject = catSchemeObj.Items.ToList().SingleOrDefault();
if(leftoverObject != null) DeleteRecursively(++currentRecursionLevel, catTree, leftoverObject);
}
之后,您可以在main方法中调用此方法,而不是循环:
DeleteRecursively(0, CatTree, CatSchemeObject);
但是我也说过,请记住,在循环中调用方法对我来说似乎毫无意义,因为除了剩下的一条路径之外你已经清除了树,所以用同一棵树调用方法, category,将导致空树(在CatSchemeObject中)。
小心!我现在注意到另一件事:在您的Items属性上调用列表,然后删除条目, NOT 会影响您的源对象,因为ToList是生成一个新对象。它保留引用的原始对象,但删除仅影响列表。因此,您必须将结果列表写回Items属性,或者在Items对象中找到直接删除的方法。 (假设它是IEnumerable而不是具体的集合类型,你应该把它写回来。)
只需使用这个简单的示例尝试一下,您就会看到原始列表未被修改。
IEnumerable<int> test = new List<int>() { 1, 2, 3, 4 , 1 };
test.ToList().RemoveAll(a => a != 1);
答案 1 :(得分:0)
编辑:
所以这是另一种可能的方式来讨论下面的讨论。 不知道你真正需要什么,所以试试吧。
int counter = 0;
var list = CatSchemeObj.Items.ToList();
//check before you call it or you will get an error
if(!list.Equals(default(list)))
{
while(true)
{
var temp = list.Where(x => CatTree[counter++] == x.Id); // or != ? play with it .
list = temp.Items.ToList().SingleOrDefault();
if(list.Equals(default(list))
{
break;
}
}
}
我刚刚将您的问题转换为2个解决方案,但我不确定您是否因为SingleOrDefault调用而导致数据丢失。它意味着“抓住第一件物品而不管一切”#39;。我知道你说你只有1个项目可以,但仍然......:)
如果这对您有用,请在评论中告诉我。
//solution 1
// inside of this loop check each child list if empty or not
foreach (var Cat in CatTree)
{
var list = CatSchemeObj.Items.ToList();
//check before you call it or you will get an error
if(!list.Equals(default(list)))
{
while(true)
{
list.RemoveAll(x => x.Id != Cat.ToString());
list = list.ToList().SingleOrDefault();
if(list.Equals(default(list))
{
break;
}
}
}
}
//solution 2
foreach (var Cat in CatTree)
{
var list = CatSchemeObj.Items.ToList();
//check before you call it or you will get an error
if(!list.Equals(default(list)))
{
CleanTheCat(cat, list);
}
}
//use this recursive function outside of loop because it will cat itself
void CleanTheCat(string cat, List<typeof(ICategorySchemeMutableObject.Items) /*Place here whatever type you have*/> CatSchemeObj)
{
CatSchemeObj.RemoveAll(x => x.Id != cat);
var catObj = CatSchemeObj.Items.ToList().SingleOrDefault();
if (!catObj.Equals(default(catObj)){
CleanTheCat(cat, catObj);
}
}
答案 2 :(得分:0)
感谢任何想要帮助的人,但我自己以一种更容易的方式解决了这个问题。
我刚将完整的CategoryScheme对象发送到以XML格式转换它的方法,然后只有一行就可以了:
XmlDocument.Descendants("Category").Where(x => !CatList.Contains(x.Attribute("id").Value)).RemoveIfExists();