我想创建一个函数
void StringFromNestedList<T>(T theList);
TheList可以是这样的类型
List<List<List<List<double>>>>
List<List<int>>
List<List<List<SomeCustomType>>>
等等。
假设对于每个元素,我想激活一个所有元素都被假定为具有的功能,如 ToString()
如果我知道嵌套的数量,以及每个列表的大小,例如2个层次,每个层次有4个元素,我会做一些像这样的事情
for (var i = 0; i < 4; i++)
{
for (var j = 0; j < 4; j++)
{
theList[i][j].ToString(); // yes, it doesnt really do anything
}
}
但我不知道需要多少个for循环。
可以做吗?
我不知道想让它通用会有什么收获。
所以,首先假设它只是需要一个 object
.
void StringFromPossibleList(object theList)
现在,假设我们不想处理列表,而是处理任何可枚举的东西。进一步假设我们已经有了这个函数--那么对于我们的可枚举里面的每一个项目,我们可以递归地调用自己的函数
{
var enu = theList as IEnumerable;
if(enu!=null)
{
foreach(var item in enu)
{
StringFromPossibleList(item);
}
}
else
{
theList.ToString();
}
}
通过使用递归,我们可以得到我们所需要的任意层次的循环。
另一种迭代解决方案可以是这样的。
public static IEnumerable<object> FlattenNestedLists(object obj)
{
var stack = new Stack();
stack.Push(obj);
while (stack.Count > 0)
{
var current = stack.Pop();
if (current is IEnumerable list)
{
foreach (var item in list)
{
stack.Push(item);
}
}
else
{
yield return current;
}
}
}
主要的好处是,对象被返回,可以被其他东西处理。缺点是潜在的框选,你可以通过一个额外的检查来避免这个问题,但是你需要考虑如果列表中包含不同对象时的行为。