.net - usar - una lista dentro de un diccionario python
¿Cómo iterar a través de Diccionario y cambiar valores? (8)
Dictionary<string,double> myDict = new Dictionary();
//...
foreach (KeyValuePair<string,double> kvp in myDict)
{
kvp.Value = Math.Round(kvp.Value, 3);
}
Me sale un error: "Propiedad o indizador ''System.Collections.Generic.KeyValuePair.Value'' no se puede asignar a - es de solo lectura."
¿Cómo puedo iterar a través de myDict
y cambiar los valores?
De acuerdo con MSDN :
La instrucción foreach es una envoltura alrededor del enumerador, que solo permite leer de la colección, no escribir en ella.
Utilizar esta:
var dictionary = new Dictionary<string, double>();
// TODO Populate your dictionary here
var keys = new List<string>(dictionary.Keys);
foreach (string key in keys)
{
dictionary[key] = Math.Round(dictionary[key], 3);
}
No debe cambiar el diccionario mientras lo itera; de lo contrario, obtendrá una excepción.
Primero copie los pares clave-valor en una lista temporal y luego repita esta lista temporal y luego cambie su diccionario:
Dictionary<string, double> myDict = new Dictionary<string, double>();
// a few values to play with
myDict["a"] = 2.200001;
myDict["b"] = 77777.3333;
myDict["c"] = 2.3459999999;
// prepare the temp list
List<KeyValuePair<string, double>> list = new List<KeyValuePair<string, double>>(myDict);
// iterate through the list and then change the dictionary object
foreach (KeyValuePair<string, double> kvp in list)
{
myDict[kvp.Key] = Math.Round(kvp.Value, 3);
}
// print the output
foreach (var pair in myDict)
{
Console.WriteLine(pair.Key + " = " + pair.Value);
}
// uncomment if needed
// Console.ReadLine();
salida (en mi máquina):
a = 2.2
b = 77777.333
c = 2.346
Nota : en términos de rendimiento, esta solución es un poco mejor que las soluciones publicadas actualmente, ya que el valor ya está asignado con la clave, y no es necesario volver a buscarlo desde el objeto del diccionario.
Noté que la manera más rápida (en este momento) de iterar sobre el diccionario con modificar es:
//Just a dumb class
class Test<T>
{
public T value;
public Test() { }
public Test(T v) { value = v; }
}
Dictionary<int, Test<object>> dic = new Dictionary<int, Test<object>>();
//Init dictionary
foreach (KeyValuePair<int, Test> pair in dic)
{
pair.Value.value = TheObject;//Modify
}
VS
List<int> keys = new List<int>(dic.Keys); //This is fast operation
foreach (int key in keys)
{
dic[key] = TheObject;
}
La primera toma alrededor de 2,2 segundos y la segunda, 4,5 segundos (tamaño de diccionario probado de 1000 y repetición de tiempo de 10k, cambiar el tamaño del diccionario a 10 no cambió las proporciones). Además, no fue un gran problema obtener la lista de claves, el valor del diccionario [clave] es simplemente lento, la iteración integrada es VS. Además, si desea aún más velocidad, utilice la clase de tipo codificado a tonto ("Prueba"), con eso obtengo aproximadamente 1.85s (con el código fijo para "objeto").
EDITAR:
Anna ha publicado la misma solución antes: https://.com/a/6515474/766304
Para los programadores perezosos:
Dictionary<string, double> dictionary = new Dictionary<string, double>();
foreach (var key in dictionary.Keys.ToList())
{
dictionary[key] = Math.Round(dictionary[key], 3);
}
Pasó un tiempo, pero tal vez alguien esté interesado en él:
yourDict = yourDict.ToDictionary(kv => k.Key, kv => Math.Round(kv.Value, 3))
Pasa por las teclas del diccionario, no por los KeyValuePairs.
Dictionary<string, double> myDict = new Dictionary<string, double>();
//...
foreach (string key in myDict.Keys)
{
myDict[key] = Math.Round(myDict[key], 3);
}
Si bien no es posible repetir el diccionario directamente porque se obtiene una excepción (como ya dijo Ron), no es necesario usar una lista temporal para resolver el problema.
En su lugar, use no foreach
, sino un ciclo for
para recorrer el diccionario y cambiar los valores con acceso indexado:
Dictionary<string, double> myDict = new Dictionary<string,double>();
//...
for(int i = 0; i < myDict.Count; i++) {
myDict[myDict.ElementAt(i).Key] = Math.Round(myDict.ElementAt(i).Value, 3);
}
Una solución sería poner las claves en una lista (u otra colección) de antemano e iterar a través de ellas mientras se cambia el diccionario:
Dictionary<string, double> dictionary = new Dictionary<string, double>();
// Populate it
List<string> keys = new List<string>(dictionary.Keys);
foreach (string key in keys)
{
dictionary[key] = Math.Round(dictionary[key], 3);
}