Loop over multiple arrays simultaneously

From Rosetta Code
Task
Loop over multiple arrays simultaneously
You are encouraged to solve this task according to the task description, using any language you may know.

Loop over multiple arrays (or lists or tuples or whatever they're called in your language) and print the ith element of each. Use your language's "for each" loop if it has one, otherwise iterate through the collection in order with some other loop.

For this example, loop over the arrays (a,b,c), (A,B,C) and (1,2,3) to produce the output

aA1
bB2
cC3

If possible, also describe what happens when the arrays are of different lengths.

ACL2

<lang Lisp>(defun print-lists (xs ys zs)

  (if (or (endp xs) (endp ys) (endp zs))
      nil
      (progn$ (cw (first xs))
              (cw "~x0~x1~%"
                  (first ys)
                  (first zs))
              (print-lists (rest xs)
                           (rest ys)
                           (rest zs)))))

(print-lists '("a" "b" "c") '(A B C) '(1 2 3))</lang>

Ada

<lang Ada>with Ada.Text_IO; use Ada.Text_IO;

procedure Array_Loop_Test is

  type Array_Index is range 1..3;
  A1 : array (Array_Index) of Character := "abc";
  A2 : array (Array_Index) of Character := "ABC";
  A3 : array (Array_Index) of Integer   := (1, 2, 3);

begin

  for Index in Array_Index'Range loop
     Put_Line (A1 (Index) & A2 (Index) & Integer'Image (A3 (Index))(2));
  end loop;

end Array_Loop_Test;</lang>

ALGOL 68

Works with: ALGOL 68 version Revision 1 - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny

<lang algol68>[]UNION(CHAR,INT) x=("a","b","c"), y=("A","B","C"), z=(1,2,3); FOR i TO UPB x DO

 printf(($ggd$, x[i], y[i], z[i], $l$))

OD</lang> Output:

aA1
bB2
cC3

AWK

<lang awk>BEGIN {

 split("a,b,c", a, ",");
 split("A,B,C", b, ",");
 split("1,2,3", c, ",");
 for(i = 1; i <= length(a); i++) {
   print a[i] b[i] c[i];
 }

}</lang>

AutoHotkey

Pseudo-arrays

StringSplit creates a pseudo-array <lang autohotkey>List1 = a,b,c List2 = A,B,C List3 = 1,2,3 MsgBox, % LoopMultiArrays()

List1 = a,b,c,d,e List2 = A,B,C,D List3 = 1,2,3 MsgBox, % LoopMultiArrays()


---------------------------------------------------------------------------

LoopMultiArrays() { ; print the ith element of each

---------------------------------------------------------------------------
   local Result
   StringSplit, List1_, List1, `,
   StringSplit, List2_, List2, `,
   StringSplit, List3_, List3, `,
   Loop, % List1_0
       Result .= List1_%A_Index% List2_%A_Index% List3_%A_Index% "`n"
   Return, Result

}</lang> An array that is too short on creation will return empty strings when trying to retrieve further elements. The 2nd Message box shows:

aA1
bB2
cC3
dD
e

Real arrays

Works with: AutoHotkey_L

In AutoHotkey_L, we can use true arrays (Objects) and the For loop. <lang AHK>List1 := ["a", "b", "c"] List2 := ["A", "B", "C"] List3 := [ 1 , 2 , 3 ] MsgBox, % LoopMultiArrays()

List1 := ["a", "b", "c", "d", "e"] List2 := ["A", "B", "C", "D"] List3 := [1,2,3] MsgBox, % LoopMultiArrays()


LoopMultiArrays() {

   local Result
   For key, value in List1
       Result .= value . List2[key] . List3[key] "`n"
   Return, Result

}</lang>The output from this script is identical to the first one.

Babel

There are two ways to do this in Babel. First, you could transpose the lists:

<lang babel>main: { (('a' 'b' 'c')('A' 'B' 'C')('1' '2' '3')) simul_array }

simul_array!:

   { trans
   { { << } each "\n" << } each }</lang>

The 'trans' operator substitutes nil in the portions of each transposed column wherever a row list was shorter than the longest row list. The '<<' operator prints nothing if the top-of-stack is nil.

A more literal solution to the problem as presented would be to iterate across each list using a user-defined cdrall operator:

<lang babel>main: { (('a' 'b' 'c')('A' 'B' 'C')('1' '2' '3')) simul_array }

simul_array!:

   {{ dup 
       { car << } each 
       cdrall }
       { allnil? not }
   while }

cdrall!: { { { cdr } each -1 take } nest }

-- only returns true if all elements of a list are nil allnil?!:

   { 1 <->
   { car nil? 
       { zap 0 last }
       { nil }
   if} each }</lang>

This solution is formally identical to the first and will handle lists of varying lengths by printing inserting nil and printing nothing for the tail ends of the short lists.

BBC BASIC

<lang bbcbasic> DIM array1$(2), array2$(2), array3%(2)

     array1$() = "a", "b", "c"
     array2$() = "A", "B", "C"
     array3%() = 1, 2, 3
     
     FOR index% = 0 TO 2
       PRINT array1$(index%) ; array2$(index%) ; array3%(index%)
     NEXT</lang>

C

Given several arrays, especially if they are heterogeneous, the most ordinary way to loop over all of them is to simply use an index variable. Determining when to stop is generally done in some application-specific way.

<lang c>#include <stdio.h>

char a1[] = {'a','b','c'}; char a2[] = {'A','B','C'}; int a3[] = {1,2,3};

int main(void) {

   for (int i = 0; i < 3; i++) {
       printf("%c%c%i\n", a1[i], a2[i], a3[i]);
   }

}</lang>

(Note: Some compilers may require a flag to accept this modern C code, such as gcc -std=c99.)

On the other hand, it is possible to write a more generic higher-order iteration scheme, as demonstrated in the following example. Here, a type for arrays with runtime-specified lengths and polymorphic printing is defined, and the iteration continues up to the length of the shortest array. <lang c>#include <stdio.h>

typedef struct closure {

   void (*f)( void *elem, void *data);
   void  *data;

} *Closure;

typedef struct listSpec{

   void (*print)(const void *);
   void *ary;
   int  count;
   size_t elem_size;

} *ListSpec;

  1. define LIST_SPEC( pf,typ,aa) {pf, aa, (sizeof(aa)/sizeof(typ)), sizeof(typ) }


/* calls closure's function f for each element in list */ void DoForEach( Closure c, ListSpec aspec ) {

   int i;
   void *val_ptr;
   for (i=0, val_ptr=aspec->ary; i< aspec->count; i++) {
       (*c->f)(val_ptr, c->data);
        val_ptr = ((char *)val_ptr) + aspec->elem_size;
   }

}

/* Used to find the minimum array length of list of lists */ void FindMin( ListSpec *paspec, int *minCount ) {

   ListSpec aspec = *paspec;
   if (*minCount>aspec->count) *minCount = aspec->count;

}

/* prints an element of a list using the list's print function */ void PrintElement( ListSpec *paspec, int *indx ) {

   ListSpec aspec = *paspec;
   (*aspec->print)( ((char*)aspec->ary) + (*indx)*aspec->elem_size);

}


/* Loop Over multiple lists (a list of lists)*/ void LoopMultiple( ListSpec arrays) {

   int indx;
   int minCount = 100000;
   struct closure c1 = { &FindMin, &minCount };
   struct closure xclsr = { &PrintElement, &indx };
   DoForEach( &c1, arrays);
   printf("min count = %d\n", minCount);
   for (indx=0; indx<minCount; indx++) {
       DoForEach(&xclsr, arrays );
       printf("\n");
   }

}

/* Defining our Lists */

void PrintInt(const int *ival) { printf("%3d,", *ival); } int ary1[] = { 6,5,4,9,8,7 }; struct listSpec lspec1 = LIST_SPEC( &PrintInt, int, ary1 );

void PrintShort(const short *ival) { printf("%3d,", *ival); } short ary2[] = { 3, 66, 20, 15, 7, 22, 10 }; struct listSpec lspec2 = LIST_SPEC( &PrintShort , short, ary2 );

void PrintStrg(const char *const *strg ) { printf(" %s", *strg); } const char *ary3[] = {"Hello", "all", "you","good", "folks","out", "there" }; struct listSpec lspec3 = LIST_SPEC( &PrintStrg , const char *, ary3 );

void PrintLstSpec(const ListSpec *ls) { printf("not-implemented"); } ListSpec listList[] = { &lspec1, &lspec2, &lspec3 }; struct listSpec llSpec = LIST_SPEC(&PrintLstSpec, ListSpec, listList);

int main(int argc, char *argv[]) {

   LoopMultiple( &llSpec);
   return 0;

}</lang>

C#

<lang csharp>class Program {

   static void Main(string[] args)
   {
       char[] a = { 'a', 'b', 'c' };
       char[] b = { 'A', 'B', 'C' };
       int[] c = { 1, 2, 3 };
       int min = Math.Min(a.Length, b.Length);
       min = Math.Min(min, c.Length);
       for (int i = 0; i < min; i++)
           Console.WriteLine("{0}{1}{2}", a[i], b[i], c[i]);
   }             

}</lang>


Using Zip:

<lang csharp> int[] numbers = { 1, 2, 3, 4 }; string[] words = { "one", "two", "three" }; Console.WriteLine(numbers.Zip(words, (first, second) => first + " " + second));

</lang>

Like a perl programmer would write it:

<lang csharp> Console.WriteLine((new[] { 1, 2, 3, 4 }).Zip(new[] { "a", "b", "c" }, (f, s) => f + " " + s)); </lang>

C++

With std::vectors: <lang cpp>#include <iostream>

  1. include <vector>

int main(int argc, char* argv[]) {

  std::vector<char> ls(3); ls[0] = 'a'; ls[1] = 'b'; ls[2] = 'c';
  std::vector<char> us(3); us[0] = 'A'; us[1] = 'B'; us[2] = 'C';
  std::vector<int> ns(3);  ns[0] = 1;   ns[1] = 2;   ns[2] = 3;
  std::vector<char>::const_iterator lIt = ls.begin();
  std::vector<char>::const_iterator uIt = us.begin();
  std::vector<int>::const_iterator nIt = ns.begin();
  for(; lIt != ls.end() && uIt != us.end() && nIt != ns.end();
      ++lIt, ++uIt, ++nIt)
  {
     std::cout << *lIt << *uIt << *nIt << "\n";
  }

}</lang>

Using static arrays: <lang cpp>#include <iostream>

int main(int argc, char* argv[]) {

  char ls[] = {'a', 'b', 'c'};
  char us[] = {'A', 'B', 'C'};
  int ns[] = {1, 2, 3};
  for(size_t li = 0, ui = 0, ni = 0;
      li < sizeof(ls) && ui < sizeof(us) && ni < sizeof(ns) / sizeof(int);
      ++li, ++ui, ++ni)
  {
     std::cout << ls[li] << us[ui] << ns[ni] << "\n";
  }

}</lang>

Clojure

<lang clojure>(doseq [s (map #(str %1 %2 %3) "abc" "ABC" "123")]

 (println s))</lang>

The sequence stops when the shortest list is exhausted.

COBOL

<lang cobol> IDENTIFICATION DIVISION.

      PROGRAM-ID. Loop-Over-Multiple-Tables.
      DATA DIVISION.
      WORKING-STORAGE SECTION.
      01  A VALUE "abc".
          03  A-Vals PIC X OCCURS 3 TIMES.
      01  B VALUE "ABC".
          03  B-Vals PIC X OCCURS 3 TIMES.
      01  C VALUE "123".
          03  C-Vals PIC 9 OCCURS 3 TIMES.
      01  I PIC 9.
      PROCEDURE DIVISION.
          PERFORM VARYING I FROM 1 BY 1 UNTIL 3 < I
              DISPLAY A-Vals (I) B-Vals (I) C-Vals (I)
          END-PERFORM
          GOBACK
          .</lang>

Common Lisp

Using functional application

<lang lisp>(mapc (lambda (&rest args)

       (format t "~{~A~}~%" args))
     '(|a| |b| |c|)
     '(a b c)
     '(1 2 3))</lang>

If lists are different lengths, it stops after the shortest one.

Using LOOP

<lang lisp>

 (loop for x in '("a" "b" "c")
       for y in '(a b c)
       for z in '(1 2 3)
       do (format t "~a~a~a~%" x y z))

</lang>

Chapel

<lang chapel>var a1 = [ "a", "b", "c" ]; var a2 = [ "A", "B", "C" ]; var a3 = [ 1, 2, 3 ];

for (x,y,z) in zip(a1, a2, a3) do

   writeln(x,y,z);</lang>

D

<lang d>import std.stdio, std.range;

void main () {

   foreach (a, b, c; zip("abc", "ABC", [1, 2, 3]))
       writeln(a, b, c);

}</lang> Output:

aA1
bB2
cC3

zip() allows to specify the stopping policy, on default it stops when the shortest range is exhausted (same as StoppingPolicy.shortest): <lang d>import std.stdio, std.range;

void main () {

   auto a1 = [1, 2];
   auto a2 = [1, 2, 3];
   alias StoppingPolicy sp;
   // Stops when the shortest range is exhausted
   foreach (p; zip(sp.shortest, a1, a2))
       writeln(p.tupleof);
   writeln();
   // Stops when the longest range is exhausted
   foreach (p; zip(sp.longest, a1, a2))
       writeln(p.tupleof);
   writeln();
   // Requires that all ranges are equal
   foreach (p; zip(sp.requireSameLength, a1, a2))
       writeln(p.tupleof);

}</lang>

Output:

11
22

11
22
03

11
22

Followed by an exception with message "Inequal-length ranges passed to Zip".

There is also std.range.lockstep: <lang d>import std.stdio, std.range;

void main() {

   auto arr1 = [1, 2, 3, 4, 5];
   auto arr2 = [6, 7, 8, 9, 10];
   foreach (ref a, ref b; lockstep(arr1, arr2))
       a += b;
   assert(arr1 == [7, 9, 11, 13, 15]);
   // Lockstep also supports iteration with an index variable
   foreach (index, a, b; lockstep(arr1, arr2))
       writefln("Index %s:  a = %s, b = %s", index, a, b);

}</lang> Lower level code that stops at the shortest length: <lang d>import std.stdio, std.algorithm;

void main () {

   auto s1 = "abc";
   auto s2 = "ABC";
   auto a1 = [1, 2];
   foreach (i; 0 .. min(s1.length, s2.length, a1.length))
       writeln(s1[i], s2[i], a1[i]);

}</lang> Output:

aA1
bB2

Delphi

<lang Delphi>program LoopOverArrays;

{$APPTYPE CONSOLE}

uses SysUtils;

const

 ARRAY1: array [1..3] of string = ('a', 'b', 'c');
 ARRAY2: array [1..3] of string = ('A', 'B', 'C');
 ARRAY3: array [1..3] of Integer = (1, 2, 3);

var

 i: Integer;

begin

 for i := 1 to 3 do
   Writeln(Format('%s%s%d', [ARRAY1[i], ARRAY2[i], ARRAY3[i]]));
 Readln;

end.</lang>

DWScript

If the arrays don't have the same bounds, an index out of bound exception will be triggered when attempting to access a non-existing element.

<lang delphi>const a1 = ['a', 'b', 'c']; const a2 = ['A', 'B', 'C']; const a3 = [1, 2, 3];

var i : Integer; for i := 0 to 2 do

  PrintLn(Format('%s%s%d', [a1[i], a2[i], a3[i]]));</lang>

E

E lacks a nice way to do this; this is to be fixed, once we figure out what to do. However, iteration over an List produces its indexes as keys, so a not entirely awful idiom exists:

<lang e>def a1 := ["a","b","c"] def a2 := ["A","B","C"] def a3 := ["1","2","3"]

for i => v1 in a1 {

   println(v1, a2[i], a3[i])

}</lang>

This will obviously fail if a2 or a3 are shorter than a1, and omit items if a2 or a3 are longer.

Given a parallel iteration utility, we might write this:

<lang e>for [v1, v2, v3] in zip(a1, a2, a3) {

   println(v1, v2, v3)

}</lang>

zip cannot yet be defined for all collections (other than by iterating over each one and storing the results in a List first); but we can define it for numeric-indexed collections such as Lists, as below. Both a definition for any number of collections and two collections is given; the latter in order to demonstrate the principle without the clutter resulting from handling a variable number of collections.

<lang e>def zip {

 to run(l1, l2) {
   def zipped {
     to iterate(f) {
       for i in int >= 0 {
         f(i, [l1.fetch(i, fn { return }),
               l2.fetch(i, fn { return })])
       }
     }
   }
   return zipped
 }
 match [`run`, lists] {
   def zipped {
     to iterate(f) {
       for i in int >= 0 {
         var tuple := []
         for l in lists {
           tuple with= l.fetch(i, fn { return })
         }
         f(i, tuple)
       }
     }
   }
   zipped
 }

}</lang>

(This will stop when the end of the shortest collection is reached.)

Efene

<lang efene>@public run = fn () {

   lists.foreach(fn ((A, B, C)) { io.format("~s~n", A, B, C) }, lists.zip3("abc", "ABC", "123"))

} </lang>

If the lists are not all the same length, an error is thrown.

Ela

<lang ela>open console list imperative

xs = zipWith3 (\x y z -> show x ++ show y ++ show z) ['a','b','c'] ['A','B','C'] [1,2,3]

each writen xs</lang>

The code above can be written shorter. First there is no need in lists as soon as strings in Ela can be treated as lists. Also instead of explicit labmda one can use partial application and a standard composition operator:

<lang ela>xs = zipWith3 (\x -> (x++) >> (++)) "abc" "ABC" "123"</lang>

Erlang

Shortest option: <lang erlang>lists:zipwith3(fun(A,B,C)-> io:format("~s~n",A,B,C) end, "abc", "ABC", "123").</lang> However, as every expression in Erlang has to return something, printing text returns 'ok'. A list with as many 'ok's as there are lines printed will thus be created. The technically cleanest way to do things would be with lists:foreach/2, which also guarantees evaluation order: <lang erlang>lists:foreach(fun({A,B,C}) -> io:format("~s~n",A,B,C) end,

             lists:zip3("abc", "ABC", "123")).</lang>

If the lists are not all the same length, an error is thrown.

Euphoria

There are many ways to do this. All of them rely on what strings really are. If they are all "strings", it's quite easy: <lang Euphoria> sequence a, b, c

a = "abc" b = "ABC" c = "123"

for i = 1 to length(a) do

   puts(1, a[i] & b[i] & c[i] & "\n")

end for </lang>

If not, and the other sequence is known to contain only integers:

<lang Euphoria> sequence a, b, c

a = "abc" b = "ABC" c = {1, 2, 3}

for i = 1 to length(a) do

   printf(1, "%s%s%g\n", {a[i], b[i], c[i]})

end for </lang>

A general solution for any arbitrary strings of characters or numbers can get a bit complex. This is because of how sequences are stored and printed out. One possible answer is as follows, if you know that only alphanumeric characters are used: <lang Euphoria> for i = 1 to length(a) do

   if (a[i] >= '0' and a[i] <= '9') then

a[i] -= '0'

   end if
   if (b[i] >= '0' and b[i] <= '9') then

b[i] -= '0'

   end if
   if (c[i] >= '0' and c[i] <= '9') then

c[i] -= '0'

   end if
   printf(1, "%s%s%s\n", {a[i], b[i], c[i]})

end for </lang> Just as in Java, using single quotes around a character gives you its "char value". In Euphoria, though, it is simply that character's code in ASCII.

With all three of the above solutions, if any of the strings are smaller than the first, it will return an error.

Factor

<lang factor>"abc" "ABC" "123" [ [ write1 ] tri@ nl ] 3each</lang>

Fantom

This will stop when it reaches the end of the shortest list. <lang fantom> class LoopMultiple {

 public static Void main ()
 {
   List arr1 := ["a", "b", "c"]
   List arr2 := ["A", "B", "C"]
   List arr3 := [1, 2, 3]
   [arr1.size, arr2.size, arr3.size].min.times |Int i|
   {
     echo ("${arr1[i]}${arr2[i]}${arr3[i]}")
   }
 }

} </lang>

Forth

<lang forth>create a char a , char b , char c , create b char A , char B , char C , create c char 1 , char 2 , char 3 ,

main
 3 0 do cr
   a i cells + @ emit
   b i cells + @ emit
   c i cells + @ emit
 loop
 cr
 a b c
 3 0 do cr
   3 0 do
     rot dup @ emit cell+
   loop
 loop
 drop drop drop
</lang>

Fortran

<lang fortran>program main

implicit none
integer,parameter :: n_vals = 3
character(len=*),dimension(n_vals),parameter :: ls = ['a','b','c']
character(len=*),dimension(n_vals),parameter :: us = ['A','B','C']
integer,dimension(n_vals),parameter          :: ns = [1,2,3]
integer :: i  !counter
do i=1,n_vals
     write(*,'(A1,A1,I1)') ls(i),us(i),ns(i)
end do

end program main </lang>

F#

<lang fsharp>for c1,c2,n in Seq.zip3 ['a';'b';'c'] ['A';'B';'C'] [1;2;3] do

 printfn "%c%c%d" c1 c2 n</lang>

When one sequence is exhausted, any remaining elements in the other sequences are ignored.

GAP

<lang gap>

  1. The Loop function will apply some function to every tuple built by taking
  2. the i-th element of each list. If one of them is exhausted before the others,
  3. the loop continues at its begining. Only the longests lists will be precessed only once.

Loop := function(a, f)

   local i, j, m, n, v;
   n := Length(a);
   v := List(a, Length);
   m := Maximum(v);
   for j in [1 .. m] do
       f(List([1 .. n], i -> a[i][1 + RemInt(j - 1, v[i])]));
   od;

end;

  1. Here we simply print each "row"

f := function(u)

   Perform(u, Print);
   Print("\n");

end;

Loop([["a", "b", "c"], ["A", "B", "C"], [1, 2, 3]], f);

aA1 bB2 cC3

Loop([["a", "b"], ["A", "B", "C", "D", "E"], [1, 2, 3]], f);

aA1 bB2 aC3 bD1 aE2</lang>

Go

Go's "for each" statement only looks at a single array (or other iterable type.) To access the three in parallel, they have to be explicitly indexed.

If a2 or a3 were shorter, the program would panic with "runtime error: index out of range." If a2 or a3 were longer, extra elements would be ignored. Go philosophy is that you should explicitly check for whatever conditions are meaningful in your application and explicitly handle whatever errors are plausible. <lang go>package main

import "fmt"

var a1 = []int{'a','b','c'} var a2 = []int{'A','B','C'} var a3 = []int{1,2,3}

func main() {

   for i := range a1 {
       fmt.Printf("%c%c%d\n", a1[i], a2[i], a3[i])
   }

}</lang>

Golfscript

<lang golfscript>["a" "b" "c"]:a; ["A" "B" "C"]:b; ["1" "2" "3"]:c; [a b c]zip{puts}/</lang>

If there are arrays of different size, the shorter are treated as "null-padded" array.


Groovy

Solution: <lang groovy>def synchedConcat = { a1, a2, a3 ->

   assert a1 && a2 && a3
   assert a1.size() == a2.size()
   assert a2.size() == a3.size()
   [a1, a2, a3].transpose().collect { "${it[0]}${it[1]}${it[2]}" }

}</lang>

Test: <lang groovy>def x = ['a', 'b', 'c'] def y = ['A', 'B', 'C'] def z = [1, 2, 3]

synchedConcat(x, y, z).each { println it }</lang>

Output:

aA1
bB2
cC3

Haskell

<lang haskell>main = mapM_ putStrLn $ zipWith3 (\a b c -> [a,b,c]) "abc" "ABC" "123"</lang> zipWith (2 lists) and zipWith3 are exported by Prelude. zipWith4 through zipWith7 are available in the Data.List module.

If lists are different lengths, it stops after the shortest one.

Haxe

<lang haxe>using Lambda; using Std;

class Main {

static function main() { var a = ['a', 'b', 'c']; var b = ['A', 'B', 'C']; var c = [1, 2, 3];

//Find smallest array var len = [a, b, c] .map(function(a) return a.length) .fold(Math.min, 0x0FFFFFFF) .int();

for (i in 0...len) Sys.println(a[i] + b[i] + c[i].string()); } }</lang>

HicEst

<lang HicEst>CHARACTER :: A = "abc" REAL :: C(3)

C = $ ! 1, 2, 3

DO i = 1, 3

  WRITE() A(i), "ABC"(i), C(i)

ENDDO</lang>

Icon and Unicon

The first solution uses co-expressions to produce parallel evaluation. <lang Icon>procedure main() a := create !["a","b","c"] b := create !["A","B","C"] c := create !["1","2","3"] while write(@a,@b,@c) end</lang>

The second solution is more like other procedural languages and also handles unequal list lengths. <lang Icon>link numbers # for max

procedure main()

a := ["a","b","c"] b := ["A","B","C","D"] c := [1,2,3]

every i := 1 to max(*a,*b,*c) do

  write(a[i]|"","\t",b[i]|"","\t",c[i]|"")

end</lang>


Uses max from numbers

J

For arrays of different types: <lang J>,.&:(":"0@>)/ 'abc' ; 'ABC' ; 1 2 3</lang> This approach works by representing the digits as characters.

Where arrays are all the same type (all numeric or all string): <lang J>,.&:>/ 'abc' ; 'ABC' ; '123'</lang>

Both of these implementations reject arrays with conflicting lengths.

Other options include:

<lang J>|: 'abc', 'ABC' ,:;":&> 1 2 3</lang> <lang J>|: 'abc', 'ABC',: '123'</lang> These implementations pad short arrays with spaces.

Or:

<lang J>|:>]&.>L:_1 'abc';'ABC';<1 2 3</lang>

This implementation puts each item from each of the original lists into a box and forms an array of boxes. (A "box" is a immutable pointer to immutable data -- in other words value semantics instead of reference semantics -- and "putting an item into a box" is obtaining one of these pointers for that item.) This implementation extends any short array by providing empty boxes to represent the missing elements.

Java

Translation of: JavaScript

<lang java>String[] a = {"a","b","c"}; String[] b = {"A","B","C"}; int[] c = {1,2,3}; for (int i = 0;i < a.length;i++) {

   System.out.println(a[i] + b[i] + c[i] + "\n");

}</lang> If the first array is too short, it will stop when it gets to the end of the first array. If one of the other arrays is too short, an ArrayIndexOutOfBoundException will be thrown.


K

<lang K>{,/$x}'+("abc";"ABC";1 2 3)</lang>

Output:

<lang K> ("aA1"

"bB2"
"cC3")    

</lang>

If the length of the arrays are different, then K croaks with "length error".

The following is a more general approach where <lang K>

     &/#:'x

</lang>

calculates the minimum length of the arrays and is used to index the first elements in each array.

<lang K>

  {+x[;!(&/#:'x)]}("abc";"ABC";"1234")

</lang>

Output:

<lang K> ("aA1"

"bB2"
"cC3")
</lang>

If the arrays are of different type then the arrays must be convert to strings.

<lang K>

  {a:,/'($:'x);+a[;!(&/#:'a)]}("abc";"ABC";1 2 3 4)

</lang>

JavaScript

This loops over the indices of the first array, and uses that to index into the others. <lang javascript>var a = ["a","b","c"],

   b = ["A","B","C"],
   c = [1,2,3],
   output = "",
   i;

for (i = 0; i < a.length; i += 1) {

   output += a[i] + b[i] + c[i] + "\n";

}</lang> If the b or c arrays are too "short", you will see the string "undefined" appear in the output.

Julia

With a higher order function: <lang Julia>julia> map(println, ('a','b','c'),('A','B','C'),(1,2,3)) ; aA1 bB2 cC3 </lang> With a loop: <lang Julia>julia> for (i,j,k) in zip(('a','b','c'),('A','B','C'),(1,2,3))

        println(i,j,k)
      end

aA1 bB2 cC3 </lang>

LFE

<lang lisp>(let ((data-1 (list 'a 'b 'c))

     (data-2 (list 'A 'B 'C))
     (data-3 (list 1 2 3)))
 (: lists zipwith3
   (lambda (i j k)
     (: io format '"~s~s~p~n" (list i j k)))
   data-1
   data-2
   data-3))

</lang>

If any of the data lists differ in size from the other, the results will print out up to the shortest data list, and then raise a function_clause error.

Erlang, and thus LFE, have zipwith and zipwith3 for working with 2 and 3 simultaneous sets of data respectively. If you need more than that, you'll need to create your own "zip" function with something like (: lists map ...).

Liberty BASIC

<lang lb>a$(1)="a" : a$(2)="b" : a$(3)="c" b$(1)="A" : b$(2)="B" : b$(3)="C" c(1)=1 : c(2)=2 : c(3)=3


for i = 1 to 3

   print a$(i);b$(i);c(i)

next</lang>

Lisaac

<lang Lisaac>Section Header

+ name := ARRAY_LOOP_TEST;

Section Public

- main <- (

 + a1, a2 : ARRAY[CHARACTER];
 + a3 : ARRAY[INTEGER];
 a1 := ARRAY[CHARACTER].create 1 to 3;
 a2 := ARRAY[CHARACTER].create 1 to 3;
 a3 := ARRAY[INTEGER].create 1 to 3;
 1.to 3 do { i : INTEGER;
   a1.put ((i - 1 + 'a'.code).to_character) to i;
   a2.put ((i - 1 + 'A'.code).to_character) to i;
   a3.put i to i;
 };
 1.to 3 do { i : INTEGER;
   a1.item(i).print;
   a2.item(i).print;
   a3.item(i).print;
   '\n'.print;
 };

);</lang>

Works with: UCB Logo

<lang logo>show (map [(word ?1 ?2 ?3)] [a b c] [A B C] [1 2 3])  ; [aA1 bB2 cC3]

(foreach [a b c] [A B C] [1 2 3] [print (word ?1 ?2 ?3)])  ; as above, one per line</lang>

Lua

This can be done with a simple for loop: <lang lua> a1, a2, a3 = {a , b , c } , { A , B , C } , { 1 , 2 , 3 } for i = 1, 3 do print(a1[i],a2[i],a3[i]) end </lang> but it may be more enlightening (and in line with the spirit of the challenge) to use the generic for: <lang lua> function iter(a, b, c)

 local i = 0
 return function()
   i = i + 1
   return a[i], b[i], c[i]
 end

end

for u, v, w in iter(a1, a2, a3) do print(u, v, w) end </lang>

Mathematica

This can be done with a built-in function: <lang mathematica> MapThread[Print, {{"a", "b", "c"}, {"A", "B", "C"}, {1, 2, 3}}]; </lang> All arguments must be lists of the same length.

Mercury

<lang>

- module multi_array_loop.
- interface.
- import_module io.
- pred main(io::di, io::uo) is det.
- implementation.
- import_module char, list, string.

main(!IO) :-

   A = ['a', 'b', 'c'],
   B = ['A', 'B', 'C'],
   C = [1, 2, 3],
   list.foldl_corresponding3(print_elems, A, B, C, !IO).
- pred print_elems(char::in, char::in, int::in, io::di, io::uo) is det.

print_elems(A, B, C, !IO) :-

   io.format("%c%c%i\n", [c(A), c(B), i(C)], !IO).

</lang> The foldl_corresponding family of procedures all throw a software_error/1 exception if the lengths of the lists are not the same.

Modula-3

<lang modula3>MODULE MultiArray EXPORTS Main;

IMPORT IO, Fmt;

TYPE ArrIdx = [1..3];

VAR

 arr1 := ARRAY ArrIdx OF CHAR {'a', 'b', 'c'};
 arr2 := ARRAY ArrIdx OF CHAR {'A', 'B', 'C'};
 arr3 := ARRAY ArrIdx OF INTEGER {1, 2, 3};

BEGIN

 FOR i := FIRST(ArrIdx) TO LAST(ArrIdx) DO
   IO.Put(Fmt.Char(arr1[i]) & Fmt.Char(arr2[i]) & Fmt.Int(arr3[i]) & "\n");
 END;

END MultiArray.</lang>

MUMPS

Pieces of String version <lang MUMPS> LOOPMULT

N A,B,C,D,%
S A="a,b,c,d"
S B="A,B,C,D"
S C="1,2,3"
S D=","
F %=1:1:$L(A,",") W !,$P(A,D,%),$P(B,D,%),$P(C,D,%)
K A,B,C,D,%
Q

</lang> When there aren't enough elements, a null string will be returned from the $Piece function.

USER>d LOOPMULT^ROSETTA
 
aA1
bB2
cC3
dD

Local arrays version <lang MUMPS> LOOPMULU

N A,B,C,D,%
S A(1)="a",A(2)="b",A(3)="c",A(4)="d"
S B(1)="A",B(2)="B",B(3)="C",B(4)="D"
S C(1)="1",C(2)="2",C(3)="3"
; will error    S %=$O(A("")) F  Q:%=""  W !,A(%),B(%),C(%) S %=$O(A(%))
S %=$O(A("")) F  Q:%=""  W !,$G(A(%)),$G(B(%)),$G(C(%)) S %=$O(A(%)) 
K A,B,C,D,%

</lang>

The commented out line will throw an <UNDEFINED> error when trying to look up D(4). Using the $Get function as a wrapper means that if the subscript for the array doesn't exist, a null string will be returned. This same syntax is used for globals (permanent variables, that have a caret "^" as the first character).

USER>D LOOPMULU^ROSETTA
 
aA1
bB2
cC3
dD
USER>D LOOPMULV^ROSETTA

aA1
bB2
cC3
dD
 S %=$O(A("")) F  Q:%=""  W !,A(%),B(%),C(%) S %=$O(A(%))
                                        ^
<UNDEFINED>LOOPMULV+5^ROSETTA *C(4)

Nemerle

It "feels" better to use zip() for this, unfortunately the built in zip() only takes two lists. <lang Nemerle>using System; using System.Console;

module LoopMultiple {

   Zip3[T1, T2, T3] (x : list[T1], y : list[T2], z : list[T3]) : list[T1 * T2 * T3]
   {
       |(x::xs, y::ys, z::zs) => (x, y, z)::Zip3(xs, ys, zs)
       |([], [], [])          => []
       |(_, _, [])            => throw ArgumentNullException()
       |(_, [], _)            => throw ArgumentNullException()
       |([], _, _)            => throw ArgumentNullException()
   }
   
   Main() : void
   {
       def first  = ['a', 'b', 'c'];
       def second = ["A", "B", "C"];
       def third  = [1, 2, 3];
       
       foreach ((x, y, z) in Zip3(first, second, third))
           WriteLine($"$x$y$z");
   }

}</lang>

Alternately:

Translation of: C#

<lang Nemerle>using System.Console;

module LoopMult {

   Main() : void
   {
       def first  = array['a', 'b', 'c'];
       def second = array['A', 'B', 'C'];
       def third  = array[1, 2, 3];
       
       when (first.Length == second.Length && second.Length == third.Length)
           foreach (i in [0 .. (first.Length - 1)])
               WriteLine("{0}{1}{2}", first[i], second[i], third[i]);
   }

}</lang>

NetRexx

<lang NetRexx>/* NetRexx */ options replace format comments java crossref savelog symbols nobinary

say 'Using arrays' aa = ['a', 'b', 'c', 'd'] bb = ['A', 'B', 'C'] cc = [1, 2, 3, 4]

loop x_ = 0 for aa.length

 do
   ax = aa[x_]
 catch ArrayIndexOutOfBoundsException
   ax = ' '
 end
 do
   bx = bb[x_]
 catch ArrayIndexOutOfBoundsException
   bx = ' '
 end
 do
   cx = cc[x_]
 catch ArrayIndexOutOfBoundsException
   cx = ' '
 end
 say ax || bx || cx
 end x_

say 'Using indexed strings (associative arrays)' ai = sampleData('a b c d') bi = sampleData('A B C') ci = sampleData('1 2 3 4')

loop x_ = 1 to ai[0]

 say ai[x_] || bi[x_] || ci[x_]
 end x_

method sampleData(arg) public static returns Rexx

 smp = ' '
 smp[0] = arg.words
 loop i_ = 1 to smp[0]
   smp[i_] = arg.word(i_)
   end i_
   
 return smp

</lang> Output:

Using arrays
aA1
bB2
cC3
d 4
Using indexed strings (associative arrays)
aA1
bB2
cC3
d 4

Objeck

<lang objeck> class MultipleArrayAccess {

 function : Main(args : String[]) ~ Nil {
   a := ["a", "b", "c"];
   b := ["A", "B", "C"];
   c := [1, 2, 3];
   
   each(i : a) {
     a[i]->Append(b[i]);
     a[i]->Append(c[i]);
     a[i]->PrintLine();
   };
 }

} </lang>

If the arrays are different lengths then an out-of-bounds error will be raised.

OCaml

an immediate solution: <lang ocaml>let a1 = [| 'a'; 'b'; 'c' |] and a2 = [| 'A'; 'B'; 'C' |] and a3 = [| '1'; '2'; '3' |] ;;

Array.iteri (fun i c1 ->

 print_char c1;
 print_char a2.(i);
 print_char a3.(i);
 print_newline()

) a1 ;;</lang>

a more generic solution could be to use a function which iterates over a list of arrays:

<lang ocaml>let n_arrays_iter ~f = function

 | [] -> ()
 | x::xs as al ->
     let len = Array.length x in
     let b = List.for_all (fun a -> Array.length a = len) xs in
     if not b then invalid_arg "n_arrays_iter: arrays of different length";
     for i = 0 to pred len do
       let ai = List.map (fun a -> a.(i)) al in
       f ai
     done</lang>

this function raises Invalid_argument exception if arrays have different length, and has this signature:

<lang ocaml>val n_arrays_iter : f:('a list -> unit) -> 'a array list -> unit</lang>

how to use it with arrays a1, a2 and a3 defined before:

<lang ocaml>let () =

 n_arrays_iter [a1; a2; a3] ~f:(fun l ->
   List.iter print_char l;
   print_newline());
</lang>

ooRexx

<lang ooRexx> x = .array~of("a", "b", "c") y = .array~of("A", "B", "C") z = .array~of(1, 2, 3)

loop i = 1 to x~size

   say x[i]y[i]z[i]

end </lang>


Oz

<lang oz>for

  I in [a b c]
  J in ['A' 'B' 'C']
  K in [1 2 3]

do

  {System.showInfo I#J#K}

end</lang>

The loop will stop when the shortest list is exhausted.

PARI/GP

This version stops when the shortest vector is exhausted. <lang parigp>loopMultiple(V)={

 my(l=#V[1]);
 for(i=2,#V,l=min(l,#V[i]));
 for(i=1,#V[1],
   for(j=1,#V,
     print1(V[j][i])
   );
   print()
 )

};</lang>

This version prints blanks when a vector is exhausted. <lang parigp>loopMultiple(V)={

 my(l=0);
 for(i=1,#V,l=max(l,#V[i]));
 for(i=1,#V[1],
   for(j=1,#V,
     if(#V[j]<i,
       print1(" ")
     ,
       print1(V[j][i])
     )
   );
   print()
 )

};</lang>

Pascal

See Delphi

Perl

<lang perl>sub zip (&@) {

       my $code = shift;
       my $min;
       $min = $min && $#$_ > $min ? $min : $#$_ for @_;
       for my $i(0..$min){ $code->(map $_->[$i] ,@_) }

} my @a1 = qw( a b c ); my @a2 = qw( A B C ); my @a3 = qw( 1 2 3 );

zip { print @_,"\n" }\(@a1, @a2, @a3);</lang>

This implementation will stop producing items when the shortest array ends.

Perl 6

Works with: niecza version 2011.07

<lang perl6>for <a b c> Z <A B C> Z 1, 2, 3 -> $x, $y, $z {

  say $x, $y, $z;

}</lang>

The Z operator stops emitting items as soon as the shortest input list is exhausted. However, short lists are easily extended by replicating all or part of the list, or by appending any kind of lazy list generator to supply default values as necessary.

Note that we can also factor out the concatenation by making the Z metaoperator apply the ~ concatenation operator across each triple: <lang perl6>for <a b c> Z~ <A B C> Z~ 1, 2, 3 -> $line { say $line; }</lang> We could also use the zip-to-string with the reduction metaoperator: <lang perl6>.say for [Z~] [<a b c>], [<A B C>], [1,2,3]</lang>

PHP

<lang PHP>$a = array('a', 'b', 'c'); $b = array('A', 'B', 'C'); $c = array('1', '2', '3'); //These don't *have* to be strings, but it saves PHP from casting them later

if ((sizeOf($a) !== sizeOf($b)) || (sizeOf($b) !== sizeOf($c))){

 throw new Exception('All three arrays must be the same length');

} foreach ($a as $key => $value){

 echo "{$a[$key]}{$b[$key]}{$c[$key]}\n";

}</lang>

This implementation throws an exception if the arrays are not all the same length.

PicoLisp

<lang PicoLisp>(mapc prinl

  '(a b c)
  '(A B C)
  (1 2 3) )</lang>

The length of the first argument list controls the operation. If subsequent lists are longer, their remaining values are ignored. If they are shorter, NIL is passed to the function.

PL/I

<lang PL/I> declare P(3) character (1) initial ('a', b', 'c'),

       Q(3) character (1) initial ('A', 'B', 'C'),
       R(3) fixed decimal (1) initial (1, 2, 3);

do i = lbound(P,1) to hbound(P,1);

  put skip edit (P(i), Q(i), R(i)) (2 A, F(1));

end; </lang>

PostScript

Library: initlib

<lang postscript> % transpose is defined in initlib like this. /transpose {

   [ exch {
       { {empty? exch pop} map all?} {pop exit} ift
       [ exch {} {uncons {exch cons} dip exch} fold counttomark 1 roll] uncons
   } loop ] {reverse} map

}.

% using it. [[/a /b /c] [/A /B /C] [1 2 3]] transpose </lang>

PowerBASIC

<lang powerbasic>FUNCTION PBMAIN () AS LONG

   DIM x(2), y(2) AS STRING * 1
   DIM z(2) AS LONG
   'data
   ARRAY ASSIGN x() = ("a", "b", "c")
   ARRAY ASSIGN y() = ("A", "B", "C")
   ARRAY ASSIGN z() = (1, 2, 3)
   'set upper bound
   C& = UBOUND(x)
   IF UBOUND(y) > C& THEN C& = UBOUND(y)
   IF UBOUND(z) > C& THEN C& = UBOUND(z)
   OPEN "output.txt" FOR OUTPUT AS 1
   FOR L& = 0 TO C&
       IF L& <= UBOUND(x) THEN PRINT #1, x(L&);
       IF L& <= UBOUND(y) THEN PRINT #1, y(L&);
       IF L& <= UBOUND(z) THEN PRINT #1, TRIM$(STR$(z(L&)));
       PRINT #1,
   NEXT
   CLOSE

END FUNCTION</lang>

Prolog

Works with SWI-Prolog <lang Prolog>multiple_arrays(L1, L2, L3) :- maplist(display, L1, L2, L3).

display(A,B,C) :- writef('%s%s%s\n', [[A],[B],[C]]). </lang> Output examples :

 ?- multiple_arrays("abc", "ABC", "123").
aA1
bB2
cC3
true.

 ?- multiple_arrays("abc", "AB", "123").
aA1
bB2
false.

PureBasic

<lang PureBasic>OpenConsole()

Fill arrays

Dim a.s(2) Dim b.s(2) Dim c(2) For Arrayposition = 0 To ArraySize(a())

 a(Arrayposition) = Chr(Asc("a") + Arrayposition)
 b(Arrayposition) = Chr(Asc("A") + Arrayposition)
 c(Arrayposition) = Arrayposition + 1

Next

loop over them

For Arrayposition = 0 To ArraySize(a())

 PrintN(a(Arrayposition) + b(Arrayposition) + Str(c(Arrayposition)))

Next Input() ;wait for Enter before ending</lang>

If they have different lengths there are two cases:
a() is the shortest one: Only elements up to maximum index of a() are printed
a() is bigger than another one: if exceeding index to much, program crashes,
else it may work because there is some "free space" after end of assigned array memory.
For example if a has size 4, line dD4 will also be printed. size 20 leads to an crash
This is because ReDim becomes slow if everytime there is a change to array size new memory has to be allocated.

Python

Using zip(): <lang python>>>> print ( '\n'.join(.join(x) for x in zip('abc', 'ABC', '123')) ) aA1 bB2 cC3 >>></lang> If lists are different lengths, zip() stops after the shortest one.

Using map(): <lang python>>>> print ( '\n'.join(map(lambda *x: .join(x), 'abc', 'ABC', '123')) ) aA1 bB2 cC3 >>></lang> If lists are different lengths, map() in Python 2.x pretends that the shorter lists were extended with None items; map() in Python 3.x stops after the shortest one.

Using itertools.imap() (Python 2.x): <lang python>from itertools import imap

def join3(a,b,c):

  print a+b+c

imap(join3,'abc','ABC','123')</lang> If lists are differnt lengths, imap() stops after the shortest is exhausted.

zip_longest

Python 3.X has zip_longest which fills shorter iterables with its fillvalue argument which defaults to None (similar to the behavior of map() in Python 2.x): <lang python>>>> from itertools import zip_longest >>> print ( '\n'.join(.join(x) for x in zip_longest('abc', 'ABCD', '12345', fillvalue='#')) ) aA1 bB2 cC3

  1. D4
    1. 5

>>></lang> (The Python 2.X equivalent is itertools.izip_longest)

R

<lang R>multiloop <- function(...) {

  # Retrieve inputs and convert to a list of character strings
  arguments <- lapply(list(...), as.character)
  
  # Get length of each input
  lengths <- sapply(arguments, length)
  # Loop over elements
  for(i in seq_len(max(lengths)))
  {
     # Loop over inputs
     for(j in seq_len(nargs()))
     {
        # print a value or a space (if that input has finished)
        cat(ifelse(i <= lengths[j], argumentsj[i], " "))
     }
     cat("\n")
  }

} multiloop(letters[1:3], LETTERS[1:3], 1:3)</lang>

Same thing as a single function call. But throws error if the arrays differ in length.

<lang R> apply(data.frame(letters[1:3], LETTERS[1:3], 1:3), 1,

     function(row) { cat(row, "\n", sep=) })

</lang>

Racket

Racket for loops can loop over an arbitrary number of sequences at once:

<lang racket>

  1. lang racket

(for ([i-1 '(a b c)]

     [i-2 '(A B C)] 
     [i-3 '(1 2 3)])
 (printf "~a ~a ~a~n" i-1 i-2 i-3))

</lang>

REXX

same size arrays

If any of the array's elements are missing or it is a short list, a blank is substituted to retain visual fidelity in the output.

When all elements are blank, then it signifies the end of the arrays. <lang rexx>/*REXX program shows how to simultaneously loop over multiple arrays.*/

x. = ' '; x.1 = "a"; x.2 = 'b'; x.3 = "c" y. = ' '; y.1 = "A"; y.2 = 'B'; y.3 = "C" z. = ' '; z.1 = "1"; z.2 = '2'; z.3 = "3"

          do j=1  until output=
          output=x.j || y.j || z.j
          say output
          end    /*j*/
                                      /*stick a fork in it, we're done.*/</lang>

output

aA1
bB2
cC3

dissimilar sized arrays

In this example, two of the arrays are extended (past the 1st example).
Also note that REXX doesn't require quotes around numbers (they're optional). <lang rexx>/*REXX program shows how to simultaneously loop over multiple arrays.*/

x.=' '; x.1="a"; x.2='b'; x.3="c"; x.4='d' y.=' '; y.1="A"; y.2='B'; y.3="C"; z.=' '; z.1= 1 ; z.2= 2 ; z.3= 3 ; z.4= 4; z.5= 5

      do j=1  until output=
      output= x.j || y.j || z.j
      say output
      end   /*j*/
                                      /*stick a fork in it, we're done.*/       </lang>

output

aA1
bB2
cC3
d 4
  5

Ruby

<lang ruby>['a','b','c'].zip(['A','B','C'], [1,2,3]) {|i,j,k| puts "#{i}#{j}#{k}"}</lang> or <lang ruby>['a','b','c'].zip(['A','B','C'], [1,2,3]) {|a| puts a.join()}</lang>

Both of these loops print aA1, bB2, cC3.

Array#zip iterates once for each element of the receiver. If an argument array is longer, the excess elements are ignored. If an argument array is shorter, the value nil is supplied.


Run BASIC

<lang runbasic>for i = 1 to 3

a$(i) = chr$(i+96)
b$(i) = chr$(i+64)
c(i)  = i

next i

for i = 1 to 3

   print a$(i);b$(i);c(i)

next</lang>

Rust

<lang rust>// rust 0.9-pre

fn main() {

   let a1 = ["a", "b", "c"];
   let a2 = ["A", "B", "C"];
   let a3 = [1, 2, 3];
   for ((&x, &y), &z) in a1.iter().zip(a2.iter()).zip(a3.iter()) {
       println!("{}{}{}", x, y, z);
   }

}</lang>

Output:
aA1
bB2
cC3

Salmon

<lang Salmon>// First, we'll define a general-purpose zip() to zip any // number of lists together. function zip(...)

 {
   variable result;
   variable list_num := 0;
   iterate(arg; arguments)
     {
       variable elem_num := 0;
       iterate (x; arg)
         {
           result[elem_num][list_num] := x;
           ++elem_num;
         };
       ++list_num;
     };
   return result;
 };

immutable a := ["a", "b", "c"],

         b := ["A", "B", "C"],
         c := [1, 2, 3];

iterate (x; zip(a, b, c))

   print(x[0], x[1], x[2], "\n");;</lang>

The preceding code will throw an exception if the lists aren't the same length. Here's an example that will print a number of lines equal to the length of the longest list and print nothing for elements that are missing if some lists are shorter than the longest:

<lang Salmon>// First, we'll define a general-purpose zip() to zip any // number of lists together. function zip(...)

 {
   variable result := [];
   variable list_num := 0;
   iterate(arg; arguments)
     {
       variable elem_num := 0;
       iterate (x; arg)
         {
           if (elem_num >= length(result))
               result[elem_num] := <<(* --> "")>>;;
           result[elem_num][list_num] := x;
           ++elem_num;
         };
       ++list_num;
     };
   return result;
 };

immutable a := ["a", "b", "c"],

         b := ["A", "B", "C"],
         c := [1, 2, 3];

iterate (x; zip(a, b, c))

   print(x[0], x[1], x[2], "\n");;</lang>

Sather

<lang sather>class MAIN is

 main is
   a :ARRAY{STR} := |"a", "b", "c"|;
   b :ARRAY{STR} := |"A", "B", "C"|;
   c :ARRAY{STR} := |"1", "2", "3"|;
   loop i ::= 0.upto!(2);
     #OUT + a[i] + b[i] + c[i] + "\n";
   end;
 end;

end;</lang>

If the index i is out of bounds, a runtime error is raised.

Scala

<lang scala> ("abc", "ABC", "123").zipped foreach { (x, y, z) =>

 println(x.toString + y + z)

} </lang>

Scheme

Scheme provides for-each and map to iterate a function over one or more lists. The map form is used to collect the results into a new list.

<lang scheme> (let ((a '("a" "b" "c"))

     (b '("A" "B" "C"))
     (c '(1 2 3)))
 (for-each 
   (lambda (i1 i2 i3) 
     (display i1) 
     (display i2) 
     (display i3) 
     (newline))
   a b c))

</lang>

Scheme has a vector datatype with constant-time retrieval of items held in an ordered sequence. Use srfi-43 to get similar iterators for vectors, vector-for-each and vector-map:

<lang scheme> (let ((a (vector "a" "b" "c"))

     (b (vector "A" "B" "C"))
     (c (vector 1 2 3)))
 (vector-for-each
   (lambda (current-index i1 i2 i3)
     (display i1) 
     (display i2) 
     (display i3) 
     (newline))
   a b c))

</lang>

Note, the lists or vectors must all be of the same length.

Standard ML

The below code will combine arbitrarily many lists of strings into a single list with length equal to that of the shortest list. <lang Standard ML> (*

* val combine_lists : string list list -> string list
*)

fun combine_lists nil = nil | combine_lists (l1::ls) = List.foldl (ListPair.map (fn (x,y) => y ^ x)) l1 ls;

(* ["a1Ax","b2By","c3Cz"] *) combine_lists[["a","b","c"],["1","2","3"],["A","B","C"],["x","y","z"]]; </lang>

Smalltalk

Works with: GNU Smalltalk

<lang smalltalk>|a b c| a := OrderedCollection new addAll: #('a' 'b' 'c'). b := OrderedCollection new addAll: #('A' 'B' 'C'). c := OrderedCollection new addAll: #(1 2 3).

1 to: (a size) do: [ :i |

 (a at: i) display.
 (b at: i) display.
 (c at: i) displayNl.

].</lang>

If index i is out of bound, a runtime error is raised.

SuperCollider

<lang SuperCollider>([\a,\b,\c]+++[\A,\B,\C]+++[1,2,3]).do({|array| array.do(_.post); "".postln })</lang>

Tcl

<lang tcl>set list1 {a b c} set list2 {A B C} set list3 {1 2 3} foreach i $list1 j $list2 k $list3 {

   puts "$i$j$k"

}</lang> If lists are different lengths, the manual [1] says: "The total number of loop iterations is large enough to use up all the values from all the value lists. If a value list does not contain enough elements for each of its loop variables in each iteration, empty values are used for the missing elements."

TorqueScript

<lang Torquescript> $var[0] = "a b c" $var[1] = "A B C"; $var[2] = "1 2 3";

for(%i=0;%i<3;%i++) echo(getWord($var[0],%i) @ getWord($var[1],%i) @ getWord($var[2],%i)); </lang>

TUSCRIPT

<lang tuscript> $$ MODE TUSCRIPT arr1="a'b'c" arr2="a'b'C" arr3="1'2'3" LOOP a=arr1,b=arr2,c=arr3 PRINT a,b,c ENDLOOP </lang> Output:

aa1
bb2
cC3

TXR

Pattern language

<lang bash>$ txr -c '@(bind a ("a" "b" "c")) @(bind b ("A" "B" "C")) @(bind c ("1" "2" "3")) @(output) @ (repeat) @a@b@c @ (end) @(end)' aA1 bB2 cC3</lang>

TXR Lisp, using mapcar

Here we actually loop over four things: three strings and an infinite list of newlines. The output is built up as one string object that is finally printed in one go.

<lang bash>$ txr -e '(pprint (mappend (op list) "abc" "ABC" "123" (repeat "\n"))))' aA1 bB2 cC3</lang>

TXR Lisp, using each

<lang bash>$ txr -e '(each ((x "abc") (y "ABC") (z "123")) (put-line `@x@y@z`))' aA1 bB2 cC3</lang>

UNIX Shell

With the Bourne shell, its for loop (from Loops/Foreach#UNIX Shell) can iterate only one list. We use an index i to access the other lists: set -- $list loads the positional parameters, and shift $i moves our element to $1.

Works with: Bourne Shell

<lang bash>a=a:b:c b=A:B:C c=1:2:3

oldifs=$IFS IFS=: i=0 for wa in $a; do set -- $b; shift $i; wb=$1 set -- $c; shift $i; wc=$1

printf '%s%s%s\n' $wa $wb $wc

i=`expr $i + 1` done IFS=$oldifs</lang>

When the lists have different lengths, this code uses the length of list a. Longer lists ignore their extra elements, and shorter lists give extra empty strings.


Some shells have real arrays, so the iteration is much more simple and easy.

Works with: bash
Works with: ksh93

<lang bash>a=(a b c) b=(A B C) c=(1 2 3) for ((i = 0; i < ${#a[@]}; i++)); do

 echo "${a[$i]}${b[$i]}${c[$i]}"

done</lang>

Works with: ksh93
Works with: pdksh

<lang bash>set -A a a b c set -A b A B C set -A c 1 2 3 ((i = 0)) while ((i < ${#a[@]})); do

 echo "${a[$i]}${b[$i]}${c[$i]}"
 ((i++))

done</lang>

Works with: zsh

<lang bash>a=(a b c) b=(A B C) c=(1 2 3) for ((i = 1; i <= $#a; i++)); do

 echo "$a[$i]$b[$i]$c[$i]"

done</lang>

C Shell

Uses the length of array a. Longer arrays ignore their extra elements, but shorter arrays force the shell to exit with an error like b: Subscript out of range.

<lang csh>set a=(a b c) set b=(A B C) set c=(1 2 3) @ i = 1 while ( $i <= $#a ) echo "$a[$i]$b[$i]$c[$i]" @ i += 1 end</lang>

Ursala

Compute the transpose of the list formed of the three lists. If they're of unequal lengths, an exception occurs. <lang Ursala>#show+

main = ~&K7 <'abc','ABC','123'></lang> output:

aA1
bB2
cC3

Wart

<lang wart>each (x X n) (zip '(a b c) '(A B C) '(1 2 3))

 prn x X n</lang>

XPL0

<lang XPL0>string 0; \use zero terminated strings include c:\cxpl\codes; \intrinsic 'code' declarations char A1, A2; int A3, I; [A1:= "abc";

A2:= "ABC";
A3:= [1,2,3];
for I:= 0 to 2 do
       [ChOut(0, A1(I));
        ChOut(0, A2(I));
       IntOut(0, A3(I));
       CrLf(0);
       ];

]</lang>

Output:

aA1
bB2
cC3

ZX Spectrum Basic

<lang zxbasic>10 LET sza = 3: REM size of a 20 LET szb = 3: REM size of b 30 LET szc = 3: REM size of c 40 DIM a$(sza): DIM b$(szb): DIM c$(szc) 50 LET max = sza: REM assume a is the biggest 60 IF szb > max THEN LET max = szb: REM now try b 70 IF szc > max THEN LET max = szc: REM or c 80 REM populate our arrays, and as a bonus we already have our demo loop 90 REM we might as well print as we populate showing the arrays in columns 100 FOR l = 1 TO max 110 IF l <= sza THEN READ a$(l): PRINT a$(l); 120 IF l <= szb THEN READ b$(l): PRINT b$(l); 130 IF l <= szc THEN READ c$(l): PRINT c$(l); 140 PRINT: REM newline 150 NEXT l 150 PRINT "The arrays are shown in columns." 160 PRINT "A$ runs down the left hand side," 170 PRINT "and C$ runs down the right." 180 STOP 200 DATA "a","b","c","A","B","C","1","2","3"</lang>