Obtendo a chave do array em um loop 'foreach'
Pergunta
Como obtenho a chave do elemento atual em um foreach
loop em C#?
Por exemplo:
PHP
foreach ($array as $key => $value)
{
echo("$value is assigned to key: $key");
}
O que estou tentando fazer em C#:
int[] values = { 5, 14, 29, 49, 99, 150, 999 };
foreach (int val in values)
{
if(search <= val && !stop)
{
// Set key to a variable
}
}
Solução
O caminho do Grauenwolf é a maneira mais direta e eficiente de fazer isso com um array:
Use um loop for ou crie uma variável temporária que você incrementa em cada passagem.
O que obviamente ficaria assim:
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
}
Com o .NET 3.5 você também pode adotar uma abordagem mais funcional, mas é um pouco mais detalhada no site e provavelmente dependeria de alguns funções de suporte para visitando os elementos em um IEnumerable.Um exagero se isso for tudo o que você precisa, mas útil se você tende a fazer muito processamento de coleta.
Outras dicas
Se você quiser chegar à chave (leia:index), então você teria que usar um loop for.Se você realmente deseja ter uma coleção que contenha chaves/valores, considerarei usar um HashTable ou um Dicionário (se quiser 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 ajude, Tyler
Com DictionaryEntry e KeyValuePair:
Baseado em
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);
}
Infelizmente, não existe uma maneira integrada de fazer isso.Use um loop for ou crie uma variável temporária que você incrementa em cada passagem.
Eu respondi isso em outra versão desta pergunta:
Foreach é para iterar as coleções que implementam Ienumerable.Faz isso chamando o Getenumerator na coleção, que retornará um enumerador.
Este enumerador tem um método e uma propriedade:
* MoveNext() * Current
Atualmente, retorna o objeto em que o enumerador está atualmente, o MoveNexext atualiza o atual para o próximo objeto.
Obviamente, o conceito de índice é estranho ao conceito de enumeração e não pode ser feito.
Por esse motivo, a maioria das coleções pode ser atravessada usando um indexador e o construto for loop.
Eu prefiro muito usar um loop para essa situação em comparação com o rastreamento do índice com uma variável local.
Como você obtém o índice da iteração atual de um loop foreach?
Na verdade, você deve usar o loop for (;;) clássico se quiser percorrer um array.Mas a funcionalidade semelhante que você obteve com seu código PHP pode ser alcançada em C# assim com um Dicionário:
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);
}
Você mesmo pode implementar essa funcionalidade usando um método de extensão.Por exemplo, aqui está uma implementação de um método de extensão KeyValuePairs que funciona em 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]);
}
}
Aqui está uma solução que acabei de encontrar 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 atualizado
enumerable.ForEach((item, index) => blah(item, index));
Método de extensão:
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);