Obtener la clave de la matriz en un bucle 'foreach'
Pregunta
¿Cómo obtengo la clave del elemento actual en un foreach
bucle en C#?
Por ejemplo:
PHP
foreach ($array as $key => $value)
{
echo("$value is assigned to key: $key");
}
Lo que estoy intentando hacer en C#:
int[] values = { 5, 14, 29, 49, 99, 150, 999 };
foreach (int val in values)
{
if(search <= val && !stop)
{
// Set key to a variable
}
}
Solución
El camino de Grauenwolf es la forma más sencilla y eficaz de hacer esto con una matriz:
Utilice un bucle for o cree una variable temporal que incremente en cada pasada.
Que por supuesto se vería así:
int[] values = { 5, 14, 29, 49, 99, 150, 999 };
for (int key = 0; key < values.Length; ++key)
if (search <= values[key] && !stop)
{
// set key to a variable
}
Con .NET 3.5 también puedes adoptar un enfoque más funcional, pero es un poco más detallado en el sitio y probablemente dependa de un par de funciones de apoyo para visitando los elementos en un IEnumerable.Excesivo si esto es todo lo que lo necesita, pero útil si tiende a realizar mucho procesamiento de colecciones.
Otros consejos
Si desea obtener la clave (lea:index) entonces tendrías que usar un bucle for.Si realmente desea tener una colección que contenga claves/valores, entonces consideraría usar una HashTable o un Diccionario (si desea usar genéricos).
Dictionary<int, string> items = new Dictionary<int, string>();
foreach (int key in items.Keys)
{
Console.WriteLine("Key: {0} has value: {1}", key, items[key]);
}
Espero que eso ayude, Tyler
Con DictionaryEntry y KeyValuePair:
Residencia en
MSDN
IDictionary<string,string> openWith = new Dictionary<string,string>()
{
{ "txt", "notepad.exe" }
{ "bmp", "paint.exe" }
{ "rtf", "wordpad.exe" }
};
foreach (DictionaryEntry de in openWith)
{
Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value);
}
// also
foreach (KeyValuePair<string,string> de in openWith)
{
Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value);
}
Pregunta SO relacionada:KeyValuePair VS Entrada de diccionario
Lamentablemente, no existe una forma integrada de hacer esto.Utilice un bucle for o cree una variable temporal que incremente en cada pasada.
Respondí esto en otra versión de esta pregunta:
Foreach es para iterar sobre colecciones que implementan IEnumerables.Lo hace llamando a Getenumerator en la colección, que devolverá un enumerador.
Este enumerador tiene un método y una propiedad:
* MoveNext() * Current
Current Devuelve el objeto en el que se encuentra Enumerator, MoveNext se actualiza actual al siguiente objeto.
Obviamente, el concepto de un índice es extraño al concepto de enumeración y no se puede hacer.
Debido a eso, la mayoría de las colecciones pueden atravesar utilizando un indexador y la construcción de bucle for.
Prefiero usar un bucle para un bucle para esta situación en comparación con el seguimiento del índice con una variable local.
¿Cómo se obtiene el índice de la iteración actual de un bucle foreach?
En realidad, deberías usar el bucle for (;;) clásico si quieres recorrer una matriz.Pero la funcionalidad similar que has logrado con tu código PHP se puede lograr en C# así con un Diccionario:
Dictionary<int, int> values = new Dictionary<int, int>();
values[0] = 5;
values[1] = 14;
values[2] = 29;
values[3] = 49;
// whatever...
foreach (int key in values.Keys)
{
Console.WriteLine("{0} is assigned to key: {1}", values[key], key);
}
Puede implementar esta funcionalidad usted mismo utilizando un método de extensión.Por ejemplo, aquí hay una implementación de un método de extensión KeyValuePairs que funciona en listas:
public struct IndexValue<T> {
public int Index {get; private set;}
public T Value {get; private set;}
public IndexValue(int index, T value) : this() {
this.Index = index;
this.Value = value;
}
}
public static class EnumExtension
{
public static IEnumerable<IndexValue<T>> KeyValuePairs<T>(this IList<T> list) {
for (int i = 0; i < list.Count; i++)
yield return new IndexValue<T>(i, list[i]);
}
}
Aquí hay una solución que se me ocurrió para este problema.
Código original:
int index=0;
foreach (var item in enumerable)
{
blah(item, index); // some code that depends on the index
index++;
}
Código actualizado
enumerable.ForEach((item, index) => blah(item, index));
Método de extensión:
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumerable, Action<T, int> action)
{
var unit = new Unit(); // unit is a new type from the reactive framework (http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx) to represent a void, since in C# you can't return a void
enumerable.Select((item, i) =>
{
action(item, i);
return unit;
}).ToList();
return pSource;
}
myKey = Array.IndexOf(values, val);