我有一个数组,它将值放在特定的索引上,如下所示:
{4: 6, 8: 1}
它有时可以在其中包含数组。我有一个从头开始构建字符串的函数,因为将数组转换为字符串会将所有索引放在该字符串中没有值,有时索引可以是数百万。
请注意,GetValue是一个单独的函数并返回一个对象,而DatabaseArray只是Player.IO使用的一种特殊类型的数组。我还要指出,我不是简单地使用foreach因为我需要显示索引。
value = "{";
DatabaseArray copiedarray = (DatabaseArray)result.GetValue(i);
for (int j = 0; j < copiedarray.Count; j++)
{
if (copiedarray.Contains(j))
{
if (value != "{")
{
value = value + ", ";
}
value = value + j + ": " + copiedarray.GetValue(j).ToString();
}
}
value = value + "}";
这适用于顶层,但不适用于任何底层阵列。它会变成这样:
{0: <null>, 1: <null>, 2: <null>, 3: {0: <null>, 1: 2}, 4: 5}
进入这个:
{3: {0: <null>, 1: 2}, 4: 5}
但我想这样做:
{3: {1: 2}, 4: 5}
我找不到让它重复并构建所有底层数组的方法。我应该注意到嵌套数组的数量是未知数,并且我不能简单地转换为字符串并删除空行,因为我在非常大的索引上得到了OutOfMemoryExceptions。
答案 0 :(得分:3)
如果我假设DatabaseArray.GetValue()可以返回另一个DatabaseArray,你可以创建一个这样的递归方法:
private string GetArrayString(object dbArray)
{
if (dbArray == null) return null;
var arrayString = "{";
var copiedarray = (DatabaseArray)dbArray;
for (var i = 0; i < copiedarray.Count; i++)
{
if (copiedarray.Contains(i))
{
if (arrayString != "{")
{
arrayString = arrayString + ", ";
}
var value = copiedarray.GetValue(i);
arrayString = arrayString + i + ": " + (value is DatabaseArray ? this.GetArrayString(value) : value);
}
}
arrayString += "}";
return arrayString;
}
然后这样称呼:
DatabaseArray copiedarray = (DatabaseArray)result.GetValue(i);
return GetArrayString(copiedarray);
那应该输出这个:
{3: {1: 2}, 4: 5}
答案 1 :(得分:1)
我就是这样做的,但我不完全确定我是否理解了你的阵列的格式。此方法假定object []数组中的每个项目都是字符串或另一个数组(然后由字符串或数组等组成)。
private static void ToFormattedString(this object[] array)
{
var res = array.Select((item, index) =>
new { Index = index, Item = item is IEnumerable<object>
? (item as object[]).ToFormattedString()
: item })
.Where(i => i.Item != null);
return "{" + string.Join(", ", res.Select(r => r.Index.ToString() + ": " + r.Item.ToString())) + "}";
}
用法:
object[] array = //Get the array
string arrayString = array.ToFormattedString();
答案 2 :(得分:1)
听起来像递归的工作!我不确定这是什么用例,但是在一个非常基础的层面上,因为你递归地写出每个数组,你应该写......好吧......一个递归方法。
public string GetArrayString()
{
var arrayValues = new object[]{
1,2,3,new[]{4,5,6}
};
return this.FormatArrayValues(arrayValues);
}
public string FormatArrayValues(IEnumerable<object> arrayValues)
{
String s = "{";
arrayValues = arrayValues.Where(w=>w != null).ToArray();
for(int j = 0; j < arrayValues.Count();j++){
var currentValue = arrayValues.ElementAt(j);
if(currentValue is int[])
{
var currentValueAsArrayOfObj = ((int[])currentValue).Cast<object>();
currentValue = this.FormatArrayValues(currentValueAsArrayOfObj);
}
s += String.Format("{0}:{1}{2}",j, currentValue, j + 1 != arrayValues.Count() ? "," : null);
}
s += "}";
return s;
}
作为旁注,如果你在数组中进行迭代,为什么还需要if (copiedarray.Contains(j)){}
这个句子...它不应该总是包含'j'。
此外,'foreach'有时是一个更清晰的循环,您可以使用Linq的'ElementAt()
'方法检索索引。在这种情况下,for-loop
可能更好,但我想我会提到它。
答案 3 :(得分:0)
由于System.Array
很特殊,因此无法直接从中继承:您的DatabaseArray
必须是数组以外的其他内容。因此,假设您的DatabaseArray
是一个类似于数组的对象,它实现了非泛型System.Collections.IList
(所有数组和类似数组的对象都做......或者应该做的事情:D)。 ..
您可以将嵌套数组视为一种树形式。
走这样一棵树是一种简单的递归算法。以下应该是你。您需要提供:
IList
)。StringBuilder
实例
Action - 一个委托方法或闭包,负责对非空数据对象进行字符串化。此visitNode
代表必须拥有签名
void visitNode( int i , object o , StringBuilder sb ) ;
所有这些Action
必须将object
及其int
索引的字符串表示附加到StringBuilder
。最简单的格式化程序就像这样简单:
visitNode( int i , object o , StringBuilder sb )
{
sb.AppendFormat( "{0} : {1}" , i , o ) ;
}
TreeWalk
完成后,StringBuilder
应该有格式化的字符串。只需调用它的ToString()
方法和bob的你的叔叔。
static void TreeWalk( IList list , StringBuilder buffer , Action<int,object,StringBuilder> visitNode , int? index )
{
// Enforce the contract's preconditions
if ( list == null ) throw new ArgumentNullException( "list" ) ;
if ( buffer == null ) throw new ArgumentNullException( "buffer" ) ;
if ( visitNode == null ) throw new ArgumentNullException( "visitNode" ) ;
// write the lead-in curly brace, prefixed with the optional index
if ( index.HasValue )
{
buffer.Append( index.Value ).Append( " : ") ;
}
buffer.Append( "{" ) ;
// visit each direct child
for ( int i = 0 ; i < list.Count ; ++i )
{
// write the item separator
if ( i > 0 )
{
buffer.Append( " , " ) ;
}
// get the current child
object child = list[i] ;
if ( child == null )
{
// if the child is null, we skip it
continue ;
}
else if ( child is IList )
{
// if the child is a [nested] IList, we recursively visit it
TreeWalk( (IList)child , buffer , visitNode ) ;
}
else
{
// if the child is anything else, it's data: just visit it
visitNode( i , child , buffer ) ;
}
}
// write the lead-out curly brace
buffer.Append( " }" ) ;
return ;
}