foreach su più elenchi contemporaneamente

2

Esistono lingue che supportano foreach su più elenchi contemporaneamente? Qualcosa del genere:

 foreach (string a in names, string b in places, string c in colors) {
      // do stuff with a, b, c
 }

Certo, questo può essere fatto con un ciclo for normale:

 for (int n = 0; n<max, n++) {
      a = names[n]; b = places[n]; c = colors[n];
 }

ma questo perde l'astrazione di foreach.

Il mio magro google-fu rivela solo persone che chiedono come fare multi-foreach in varie lingue che non lo supportano. Suppongo che il linguaggio alcuni lo usi, ma non riesco a capire quale.

    
posta Joe 18.05.2013 - 20:01
fonte

2 risposte

8

Certo, Python può farlo:

for a, b, c in zip(names, places, colors):
    pass

zip crea un elenco di tuple dai iterabili passati ad esso. Il ciclo for di Python supporta "disimballaggio", vale a dire che le tuple sono suddivise in componenti. È una forma debole di abbinamento di modelli.

    
risposta data 18.05.2013 - 20:21
fonte
3
  • In C #, puoi trasformare più raccolte in una raccolta di tuple, quindi utilizzare foreach . Non esiste una sintassi specifica del linguaggio, ma .NET Framework ti consente comunque di farlo.

  • In SQL, puoi utilizzare join . Non sono sicuro che le "lingue" che stai cercando si estendano a SQL.

Nota che in tutti i casi c'è un'ambiguità con il tuo semplice. Cosa succede se colors.length < places.length ? Se places.length > names.length , i posti rimanenti saranno semplicemente scartati?

Esempio di C #:

public static void Main(string[] args)
{
    var names = new[] { "John", "Bill", "Joel" };
    var places = new[] { 1, 2, 3 };
    var colors = new[] { Color.AliceBlue, Color.BlueViolet, Color.DarkMagenta };

    var zip = names.Zip(places, (n, p) => new { n, p }).Zip(colors, (t, c) => new { Name = t.n, Place = t.p, Color = c });

    foreach (var z in zip)
    {
        Console.WriteLine(string.Join(", ", new[] { (object)z.Name, z.Place, z.Color }));
    }

    Console.WriteLine("Press any key to continue...");
    Console.ReadKey(true);
}

Oppure, utilizzando un metodo di estensione:

public static IEnumerable<Tuple<T1, T2, T3>> ZipSeveral<T1, T2, T3>(this IEnumerable<T1> first, IEnumerable<T2> second, IEnumerable<T3> third)
{
    return first.Zip(second, (a, b) => new { a, b }).Zip(third, (t, c) => Tuple.Create(t.a, t.b, c));
}

puoi ridurre il codice a un semplice foreach :

foreach (var z in names.ZipSeveral(places, colors))
{
    Console.WriteLine(string.Join(", ", new[] { (object)z.Item1, z.Item2, z.Item3 }));
}
    
risposta data 18.05.2013 - 21:16
fonte

Leggi altre domande sui tag