Ger*_*ero 1 c# arrays dictionary
我有一个包含字符串和字典的字符串数组.
String [] str_array;
Dictionary<int, string> dict = new Dictionary<int, string>();
dict = str_array.toDictionary();
Run Code Online (Sandbox Code Playgroud)
如何使用int和String将数组放入字典?我已经看过bool所有这些例子,但我需要int和string.
int(key)只是字典(dict.count)的实际位置,值将是该位置的数组值.
编辑:thx到所有答案,但我不想迭代数组.我假设使用array.toDictionary,性能优于迭代数组,只是将数组的值赋给字典.数组可能有5k个元素.
edit2:原因是我必须将字典传递给方法......需要它.我所有的值都在一个简单的数组中.
edit3:最重要的是性能.也许迭代数组并为dict赋值比array.toDictionary更快,但问题是我没有那么小的代码来对这两者进行基准测试.
首先 - 你对性能的问题很有趣并且过早优化 - 正如这个答案所表明的那样,你可能会看到一个for循环和之间的性能差异只有几毫秒ToDictionary.
除非你在实时系统中运行它,否则我看不出太多问题.
在节目中 - 以下是我可以想到的三种(半)不同方式构建字典的粗略基准(只有现实世界时间是可靠的).第一个使用for循环,第二个使用相同但不使用数组的Length属性(仅用于感兴趣); 第三次和第四次使用ToDictionary; 一个使用a Select和一个使用计数器变量(混合):
[TestMethod]
public void SomeBenchmark()
{
List<double> forLoopTimes = new List<double>();
List<double> forLoop2Times = new List<double>();
List<double> toDictionaryTimes = new List<double>();
List<double> hybridTimes = new List<double>();
string[] array = Enumerable.Range(0, 5000).Select(i => i.ToString()).ToArray();
Dictionary<int, string> dictionary;
int runCount = 5000;
int arrayLen = array.Length;
while (runCount-- != 0)
{
Stopwatch sw = Stopwatch.StartNew();
dictionary = new Dictionary<int, string>();
for (int i = 0; i < array.Length; i++)
{
dictionary[i] = array[i];
}
sw.Stop();
forLoopTimes.Add(sw.Elapsed.TotalMilliseconds);
sw.Restart();
dictionary = new Dictionary<int, string>();
for (int i = 0; i < arrayLen; i++)
{ //same as before - but using arrayLen instead of property
dictionary[i] = array[i];
}
sw.Stop();
forLoop2Times.Add(sw.Elapsed.TotalMilliseconds);
sw.Restart();
dictionary = array.Select((s, i) => new { Key = i, Value = s }).ToDictionary(v => v.Key, v => v.Value);
sw.Stop();
toDictionaryTimes.Add(sw.Elapsed.TotalMilliseconds);
int counter = 0;
sw.Restart();
dictionary = array.ToDictionary(s => counter++, s => s);
sw.Stop();
hybridTimes.Add(sw.Elapsed.TotalMilliseconds);
}
Console.WriteLine("for loop average: {0} milliseconds", forLoopTimes.Average());
Console.WriteLine("for loop(2) average: {0} milliseconds", forLoop2Times.Average());
Console.WriteLine("ToDictionary average: {0} milliseconds", toDictionaryTimes.Average());
Console.WriteLine("Hybrid average: {0} milliseconds", hybridTimes.Average());
}
Run Code Online (Sandbox Code Playgroud)
结果(发布版本,在我的Dell 2.4Ghz工作站上运行大约需要20秒):
对于循环平均值:0.28880804毫秒
对于循环(2)平均值:0.2773845毫秒
ToDictionary平均值:0.479094339999998毫秒
混合平均值:0.353655779999999毫秒
因此,for循环无疑更快 - 至少是最接近ToDictionary实现的22%.我用100,000个元素尝试了它,然后它达到了约30%.
注意第二个for循环结果 - 似乎建议绕过Length属性是个好主意.事实上,我连续完成了4次运行,这些结果(包括第一次,从上面开始):
For loop:0.28880804,0.28562478,0.283770739999999,0.287241679999999
对于环(2):0.2773845,0.27621306,0.27869996,0.27962916
ToDictionary:0.479094339999998,0.476417939999997,0.476162219999997,0.475776479999997
Hybrid:0.353655779999999,0.3583224,0.352022739999998,0.349865779999999
然而,我已经看到结果也至少转变为一个基准测试结果 - 证明了这种基准测试可能有多么无意义.实际上我们应该为每个测试生成一个不同的数组,以避免缓存等.
还有另一种选择.
如果你正在调用的方法接受IDictionary<int, string>(注意 - 接口); 而不是Dictionary<int, string>你可以创建一个简单的包装器类型,实现接口的必要成员,从而避免投入到词典中的需要; 只要只需要某些成员.这是一个几乎完整的实现:
public class FakeDictionary : IDictionary<int, string>
{
private readonly string[] _array;
public FakeDictionary(string[] array)
{
_array = array;
}
#region IDictionary<int,string> Members
public void Add(int key, string value)
{
throw new NotSupportedException();
}
public bool ContainsKey(int key)
{
return key >= 0 && key < _array.Length;
}
public ICollection<int> Keys
{
get { return Enumerable.Range(0, _array.Length).ToArray(); }
}
public bool Remove(int key)
{
throw new NotSupportedException();
}
public bool TryGetValue(int key, out string value)
{
value = null;
if (key >= 0 && key < _array.Length)
{
value = _array[key];
return true;
}
return false;
}
public ICollection<string> Values
{
get { return _array; }
}
public string this[int key]
{
get
{
try
{
return _array[key];
}
catch (ArgumentOutOfRangeException ex)
{
throw new KeyNotFoundException("Invalid key", ex);
}
}
set //note - can't be used to add items
{
try
{
_array[key] = value;
}
catch (ArgumentOutOfRangeException ex)
{
throw new KeyNotFoundException("Invalid key", ex);
}
}
}
#endregion
#region ICollection<KeyValuePair<int,string>> Members
public void Add(KeyValuePair<int, string> item)
{
throw new NotSupportedException();
}
public void Clear()
{
throw new NotSupportedException();
}
public bool Contains(KeyValuePair<int, string> item)
{
return ContainsKey(item.Key) && _array[item.Key].Equals(item.Value);
}
public void CopyTo(KeyValuePair<int, string>[] array, int arrayIndex)
{
//too much for an SO answer.
throw new NotImplementedException();
}
public int Count
{
get { return _array.Length; }
}
public bool IsReadOnly
{
//technically it's not - because we can modify individual elements -
//but at the collection-level it is
get { return true; }
}
public bool Remove(KeyValuePair<int, string> item)
{
throw new NotSupportedException();
}
#endregion
#region IEnumerable<KeyValuePair<int,string>> Members
public IEnumerator<KeyValuePair<int, string>> GetEnumerator()
{
throw new NotImplementedException();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)