我希望构建一个函数来创建一个或多个列表。
此元素列表根据动态列表列表中的值确定独奏。
例如 列表A保存一个包含列表B的对象,列表B包含一个包含列表C的对象
在列表A B或C中,他们有可能持有特殊值。
我需要创建一个搜索每个列表的函数,只返回保存特殊值的值。
我试着研究递归函数,我认为我很接近。
public ObservableCollection<ListViewItem> RecursiveActionBuilder(List<IMetaData> pList)
{
if (pList == null)
return null;
List<ActionObject> actions = new List<ActionObject>();
for (int x = 0; x < pList.Count; x++)
{
ActionObject child = RecursiveActionBuilder(pList[x]);
if (child == null)
continue;
else
actions.Add(child);
}
ObservableCollection<ListViewItem> items = new ObservableCollection<Models.Items.ListViewItem>();
for (int x = 0; x < actions.Count; x++)
items.Add(new ListViewItem()
{
Values = new ListViewValue[]
{
new ListViewValue() { Value = actions[x].Command },
new ListViewValue() { Value = actions[x].Target },
new ListViewValue() { Value = actions[x].Value },
new ListViewValue() { Value = actions[x].Comment }
}
});
return items;
}
public ActionObject RecursiveActionBuilder(IMetaData pObj)
{
if (pObj == null)
return null;
if (pObj.Children == null)
{
if (pObj.Tag == Enums.TestType.Action)
return pObj as ActionObject;
else
return null;
}
ActionObject action = new ActionObject();
for (int x = 0; x < pObj.Children.Count; x++)
{
ActionObject child = RecursiveActionBuilder(pObj.Children[x]);
if (child == null)
continue;
else return child;
}
return null;
}
然而,它并没有抓住所有的行动&#39;它只抓一个,然后跳出来。
思想?
答案 0 :(得分:2)
问题显然是因为这种方法
public ActionObject RecursiveActionBuilder(IMetaData pObj)
返回单个对象,而不是问题所暗示的多个对象。
可以修复,但我会建议你采用略有不同的方法。
遵循DRY原则,在这种情况下你真正需要的是类似LINQ的方法,它会像你的IMetaData
那样展平树结构(根据你的代码包含List<IMetaData> Children
属性/字段)。例如,您可以使用我对How to flatten tree via LINQ?:
public static class TreeHelpers
{
public static IEnumerable<T> Expand<T>(
this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector)
{
var stack = new Stack<IEnumerator<T>>();
var e = source.GetEnumerator();
try
{
while (true)
{
while (e.MoveNext())
{
var item = e.Current;
yield return item;
var elements = elementSelector(item);
if (elements == null) continue;
stack.Push(e);
e = elements.GetEnumerator();
}
if (stack.Count == 0) break;
e.Dispose();
e = stack.Pop();
}
}
finally
{
e.Dispose();
while (stack.Count != 0) stack.Pop().Dispose();
}
}
}
现在,您可以利用LINQ的全部功能来解决您的具体问题:
public ObservableCollection<ListViewItem> RecursiveActionBuilder(List<IMetaData> pList)
{
if (pList == null)
return null;
var items = pList
.Expand(e => e.Children)
.Select(e => e.Children == null && e.Tag == Enums.TestType.Action ? e as ActionObject : null)
.Where(e => e != null)
.Select(e => new ListViewItem()
{
Values = new ListViewValue[]
{
new ListViewValue() { Value = e.Command },
new ListViewValue() { Value = e.Target },
new ListViewValue() { Value = e.Value },
new ListViewValue() { Value = e.Comment }
}
});
return new ObservableCollection<ListViewItem>(items);
}