方法签名:
public static string TraverseList(string prefix, object list)
输入:
prefix: "Boo"
list: new object[] { "a string", new[] { "a", "b", "c" }, "spam", new[] { "eggs" }, new[] { new[] { "one", "two" }, new[] { "three", "four" } } }
预期输出:
Boo.0: a string
Boo.1.0: a
Boo.1.1: b
Boo.1.2: c
Boo.2: spam
Boo.3.0: eggs
Boo.4.0.0: one
Boo.4.0.1: two
Boo.4.1.0: three
Boo.4.1.1: four
我尝试实现这个:
public static string TraverseList(string prefix, object list)
{
int index = 0;
int index1 = 0;
int index2 = 0;
StringBuilder dumpListBuilder = new StringBuilder();
if (list is Array)
{
foreach (var obj in (Array)list)
{
if (obj is Array)
{
foreach (var obj1 in (Array)obj)
{
if (obj1 is Array)
{
foreach (var obj2 in (Array)obj1)
{
dumpListBuilder.AppendFormat("{0}.{1}.{2}.{3}: {4}{5}", prefix, index, index1, index2, obj2, Environment.NewLine);
index2++;
}
}
else
{
dumpListBuilder.AppendFormat("{0}.{1}.{2}: {3}{4}", prefix, index, index1, obj1, Environment.NewLine);
}
index1++;
index2 = 0;
}
}
else
{
dumpListBuilder.AppendFormat("{0}.{1}: {2}{3}", prefix, index, obj, Environment.NewLine);
}
index++;
index1 = 0;
}
}
return dumpListBuilder.ToString();
}
它有效,但效率不高,仅限于3个嵌套列表的深度。任何人都可以建议无限深度的最佳解决方案吗?
我知道我应该使用递归,但是如何在不更改方法签名的情况下这样做?
答案 0 :(得分:8)
递归是这里的关键
static void Main( string[] args )
{
var prefix = "Foo";
var input = new object[] { "a string", new[] { "a", "b", "c" }, "spam", new[] { "eggs" }, new[] { new[] { "one", "two" }, new[] { "three", "four" } } };
var output = DumpList( prefix, input );
Console.WriteLine( output );
}
static string DumpList( string prefix, object list )
{
var collection = !( list is string )
? list as IEnumerable
: null;
return collection != null
? string.Join(
separator: Environment.NewLine,
values: collection.Cast<object>().Select( ( o, i ) => DumpList( $"{prefix}.{i}", o ) ) )
: $"{prefix}: {list}";
}
答案 1 :(得分:6)
您可以使用recursion
<强>矿强>
public static string DumpList(string prefix, object list)
{
if (list is object[] array)
return String.Join("\r\n", array.Select((value, i) => DumpList($"{prefix}.{i}", value)));
return $"{prefix}: {list}";
}
<强> MineOriginal 强>
public static void DumpList2(string prefix, object input, List<string> result)
{
if (input is object[] ary)
for (var i = 0; i < ary.Length; i++)
if (ary[i] is Array)
DumpList2($"{prefix}.{i}", ary[i], result);
else
result.Add($"{prefix}.{i}.{ary[i]}");
else
result.Add($"{prefix}.0.{input}");
}
Mode : Release
Test Framework : .NET Framework 4.7.1
Benchmarks runs : 100 times (averaged)
Scale : 100
Name | Time | Range | StdDev | Cycles | Pass
-----------------------------------------------------------------
MineOriginal | 0.550 ms | 0.311 ms | 0.15 | 1,853,187 | Yes
Original | 0.612 ms | 0.361 ms | 0.13 | 2,059,844 | Base
Mine | 0.697 ms | 0.012 ms | 0.08 | 2,368,041 | Yes
SirRufo | 0.776 ms | 0.022 ms | 0.15 | 2,635,368 | Yes
Jimi | 0.821 ms | 0.012 ms | 0.21 | 2,779,449 | Yes
JimiNoFormat | 0.873 ms | 0.007 ms | 0.23 | 2,950,638 | Yes
Scale : 1,000
Name | Time | Range | StdDev | Cycles | Pass
------------------------------------------------------------------
MineOriginal | 4.461 ms | 0.541 ms | 0.21 | 15,185,195 | Yes
Original | 5.914 ms | 0.346 ms | 1.15 | 20,015,882 | Base
Mine | 6.725 ms | 0.153 ms | 0.31 | 22,890,735 | Yes
JimiNoFormat | 6.818 ms | 0.335 ms | 0.23 | 23,193,642 | Yes
Jimi | 6.873 ms | 0.633 ms | 0.37 | 23,382,543 | Yes
SirRufo | 7.198 ms | 1.004 ms | 0.70 | 24,512,923 | Yes
Scale : 10,000
Name | Time | Range | StdDev | Cycles | Pass
--------------------------------------------------------------------
Original | 57.283 ms | 3.049 ms | 5.70 | 194,331,610 | Base
MineOriginal | 67.833 ms | 5.618 ms | 2.66 | 230,951,862 | Yes
Mine | 72.695 ms | 2.624 ms | 3.39 | 246,760,230 | Yes
Jimi | 73.571 ms | 4.007 ms | 2.00 | 249,736,001 | Yes
JimiNoFormat | 73.659 ms | 2.204 ms | 2.92 | 249,493,594 | Yes
SirRufo | 74.141 ms | 2.395 ms | 2.64 | 251,712,472 | Yes
<强>说明强>
JimiNoFormat只是一个使用带有字符串插值的代码的版本
Scale基本上是连接和合并多次的原始数组,以制作一个超级duper大小的数组来测试
MineOriginal基本上只使用一个列表,并在最后将其转换为字符串,它的效率更高,然后使用整个字符串,但它不能很好地扩展,最终会因极大的数据集而丢失
<强>摘要强>
递归广告的开销更大,但不是太糟糕
答案 2 :(得分:1)
<强> [For benchmarking purposes]
强>
在没有空检查的情况下,对@Sir Rufo编码的程序进行详细说明:
(.NET Framework 4.7.1 - C# 7.3
)
var prefix = "Foo";
var input = new object[] { "a string", new[] { "a", "b", "c" }, "spam", new[] { "eggs" }, new[] { new[] { "one", "two" }, new[] { "three", "four" } } };
string output = DumpList(prefix, input);
Console.WriteLine(output);
static string DumpList(string prefix, object list) => (list is string)
? $"{prefix}: {list}"
: string.Join(Environment.NewLine,
((IEnumerable)list).Cast<object>().Select((obj, idx) =>
DumpList($"{prefix}.{idx}", obj)));