⚠️ Warning: This is a draft ⚠️

This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.

If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.

;Task: Loop over multiple arrays (or lists or tuples or whatever they're called in your language) and display the ''i'' th 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) (1,2,3) to produce the output: aA1 bB2 cC3

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

• [[Loop over multiple arrays simultaneously]]
• [[Loops/Break]]
• [[Loops/Continue]]
• [[Loops/Do-while]]
• [[Loops/Downward for]]
• [[Loops/For]]
• [[Loops/For with a specified step]]
• [[Loops/Foreach]]
• [[Loops/Increment loop index within loop body]]
• [[Loops/Infinite]]
• [[Loops/N plus one half]]
• [[Loops/Nested]]
• [[Loops/While]]
• [[Loops/with multiple ranges]]
• [[Loops/Wrong ranges]]

360 Assembly

*        Loop over multiple arrays simultaneously  09/03/2017
LOOPSIM  CSECT
USING  LOOPSIM,R12        base register
LR     R12,R15
LA     R6,1               i=1
LA     R7,3               counter=3
LOOP     LR     R1,R6              i
SLA    R1,1               *2
LH     R2,R-2(R1)         r(i)
XDECO  R2,PG              edit r(i)
LA     R1,S-1(R6)         @s(i)
MVC    PG+3(1),0(R1)      output s(i)
LA     R1,Q-1(R6)         @q(i)
MVC    PG+7(1),0(R1)      output q(i)
XPRNT  PG,80              print s(i),q(i),r(i)
LA     R6,1(R6)           i++
BCT    R7,LOOP            decrement and loop
BR     R14                exit
S        DC     C'a',C'b',C'c'
Q        DC     C'A',C'B',C'C'
R        DC     H'1',H'2',H'3'
PG       DC     CL80' '            buffer
YREGS
END    LOOPSIM

{{out}}

a   A   1
b   B   2
c   C   3

ACL2

(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))

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;

ALGOL 68

{{works with|ALGOL 68|Revision 1 - no extensions to language used}}

1.18.0-9h.tiny]}} {{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download

1.8-8d] - due to extensive use of '''format'''[ted] ''transput''}}

[]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

{{out}}

aA1
bB2
cC3

ALGOL W

begin
% declare the three arrays                                               %
string(1) array a, b ( 1 :: 3 );
integer   array c    ( 1 :: 3 );
% initialise the arrays - have to do this element by element in Algol W  %
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;
% loop over the arrays                                                   %
for i := 1 until 3 do write( i_w := 1, s_w := 0, a(i), b(i), c(i) );
end.

If the arrays are not the same length, a subscript range error would occur when a non-existant element was accessed.

AppleScript

{{Trans|JavaScript}} (Functional ES 5 zipListsWith version)

If we have a generic Applescript '''map''' function, we can use it to write a generic '''zipListsWith''', which applies a given function over lists derived from the nth members of an arbitrary list of (equal-length) lists. (Where lists are of uneven length, items beyond the maximum shared length are ignored).

-- ZIP LISTS WITH FUNCTION ---------------------------------------------------

-- zipListsWith :: ([a] -> b) -> [[a]] -> [[b]]
on zipListsWith(f, xss)
set n to length of xss

script
on |λ|(_, i)
script
on |λ|(xs)
item i of xs
end |λ|
end script

if i  n then
apply(f, (map(result, xss)))
else
{}
end if
end |λ|
end script

if n > 0 then
map(result, item 1 of xss)
else
[]
end if
end zipListsWith

-- TEST  ( zip lists with concat ) -------------------------------------------
on run

intercalate(linefeed, ¬
zipListsWith(concat, ¬
[["a", "b", "c"], ["A", "B", "C"], [1, 2, 3]]))

end run

-- GENERIC FUNCTIONS ---------------------------------------------------------

-- apply (a -> b) -> a -> b
on apply(f, a)
mReturn(f)'s |λ|(a)
end apply

-- concat :: [[a]] -> [a] | [String] -> String
on concat(xs)
if length of xs > 0 and class of (item 1 of xs) is string then
set acc to ""
else
set acc to {}
end if
repeat with i from 1 to length of xs
set acc to acc & item i of xs
end repeat
acc
end concat

-- intercalate :: Text -> [Text] -> Text
on intercalate(strText, lstText)
set {dlm, my text item delimiters} to {my text item delimiters, strText}
set strJoined to lstText as text
set my text item delimiters to dlm
return strJoined
end intercalate

-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map

-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn

{{Out}}

aA1
bB2
cC3

But a transpose function might be simpler:

-- CONCAT MAPPED OVER A TRANSPOSITION ----------------------------------------
on run

unlines(map(concat, transpose([["a", "b", "c"], ["A", "B", "C"], [1, 2, 3]])))

end run

-- GENERIC FUNCTIONS ---------------------------------------------------------

-- concat :: [[a]] -> [a] | [String] -> String
on concat(xs)
if length of xs > 0 and class of (item 1 of xs) is string then
set acc to ""
else
set acc to {}
end if
repeat with i from 1 to length of xs
set acc to acc & item i of xs
end repeat
acc
end concat

-- intercalate :: String -> [String] -> String
on intercalate(s, xs)
set {dlm, my text item delimiters} to {my text item delimiters, s}
set str to xs as text
set my text item delimiters to dlm
return str
end intercalate

-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map

-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn

-- transpose :: [[a]] -> [[a]]
on transpose(xss)
script column
on |λ|(_, iCol)
script row
on |λ|(xs)
item iCol of xs
end |λ|
end script

map(row, xss)
end |λ|
end script

map(column, item 1 of xss)
end transpose

-- unlines :: [String] -> String
on unlines(xs)
intercalate(linefeed, xs)
end unlines

{{Out}}

aA1
bB2
cC3

AutoHotkey

=== Pseudo-arrays === [http://www.autohotkey.com/docs/commands/StringSplit.htm StringSplit] creates a pseudo-array

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
}

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 ([http://l.autohotkey.com/docs/Objects.htm Objects]) and the [http://l.autohotkey.net/docs/commands/For.htm For loop].

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
}

The output from this script is identical to the first one.

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];
}
}

Axe

Note that in this example, we use a few bytes from each of L₁, L₂, and L₃ for simplicity. In practice, one would want to arrange the arrays to all fit within L₁ to avoid volatility issues with L₂ and L₃.

'a'→{L₁}
'b'→{L₁+1}
'c'→{L₁+2}
'A'→{L₂}
'B'→{L₂+1}
'C'→{L₂+2}
1→{L₃}
2→{L₃+1}
3→{L₃+2}
For(I,0,2)
Disp {L₁+I}►Char,{L₂+I}►Char,{L₃+I}►Dec,i
End

Babel

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

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

simul_array!:
{ trans
{ { << } each "\n" << } each }

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:

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 }

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

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

Befunge

There's no concept of an array data type in Befunge, but you'd typically store your arrays as sequences of data in the Befunge code space. You'd then loop over the range of indices required to access those arrays, and use the loop variable as an offset into each data area. For arrays of differing lengths, you'd need to manually check for an out-of-range index and deal with it appropriately.

:2g,:3g,:4gv
@_^#`2:+1,+55,<
abc
ABC
123

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.

#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]);
}
}

(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 [[Loop_over_multiple_arrays_simultaneously/C-Elaboration|this example]]. There, 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.

C#

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]);
}
}

Using Enumerable.Zip (stops when either source runs out of elements):

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

Like how a perl programmer would write it (still using Zip):

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

Custom implementation for arrays of different lengths that pads with spaces after the end of the shorter arrays:

public static void Multiloop(char[] A, char[] B, int[] C)
{
var max = Math.Max(Math.Max(A.Length, B.Length), C.Length);
for (int i = 0; i < max; i++)
Console.WriteLine(\$"{(i < A.Length ? A[i] : ' ')}, {(i < B.Length ? B[i] : ' ')}, {(i < C.Length ? C[i] : ' ')}");
}

usage:

Multiloop(new char[] { 'a', 'b', 'c', 'd' }, new char[] { 'A', 'B', 'C' }, new int[] { 1, 2, 3, 4, 5 });

C++

With std::vectors:

#include <iostream>
#include <vector>

int main(int argc, char* argv[])
{
std::vector<char> ls(3); ls = 'a'; ls = 'b'; ls = 'c';
std::vector<char> us(3); us = 'A'; us = 'B'; us = 'C';
std::vector<int> ns(3);  ns = 1;   ns = 2;   ns = 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";
}
}

Using static arrays:

#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";
}
}

C++11

With std::vectors:

#include <iostream>
#include <vector>

int main(int argc, char* argv[])
{
auto lowers = std::vector<char>({'a', 'b', 'c'});
auto uppers = std::vector<char>({'A', 'B', 'C'});
auto nums = std::vector<int>({1, 2, 3});

auto ilow = lowers.cbegin();
auto iup = uppers.cbegin();
auto inum = nums.cbegin();

for(; ilow != lowers.end()
and iup != uppers.end()
and inum != nums.end()
; ++ilow, ++iup, ++inum)
{
std::cout << *ilow << *iup << *inum << "\n";
}
}

Using static arrays:

#include <iostream>
#include <iterator>

int main(int argc, char* argv[])
{
char lowers[] = {'a', 'b', 'c'};
char uppers[] = {'A', 'B', 'C'};
int nums[] = {1, 2, 3};

auto ilow = std::begin(lowers);
auto iup = std::begin(uppers);
auto inum = std::begin(nums);

for(; ilow != std::end(lowers)
and iup != std::end(uppers)
and inum != std::end(nums)
; ++ilow, ++iup, ++inum )
{
std::cout << *ilow << *iup << *inum << "\n";
}
}

With std::arrays:

#include <iostream>
#include <array>

int main(int argc, char* argv[])
{
auto lowers = std::array<char, 3>({'a', 'b', 'c'});
auto uppers = std::array<char, 3>({'A', 'B', 'C'});
auto nums = std::array<int, 3>({1, 2, 3});

auto ilow = lowers.cbegin();
auto iup = uppers.cbegin();
auto inum = nums.cbegin();

for(; ilow != lowers.end()
and iup != uppers.end()
and inum != nums.end()
; ++ilow, ++iup, ++inum )
{
std::cout << *ilow << *iup << *inum << "\n";
}
}

With std::arrays by indexes:

#include <iostream>
#include <array>
#include <algorithm>

int main(int argc, char* argv[])
{
auto lowers = std::array<char, 3>({'a', 'b', 'c'});
auto uppers = std::array<char, 3>({'A', 'B', 'C'});
auto nums = std::array<int, 3>({1, 2, 3});

auto const minsize = std::min(
lowers.size(),
std::min(
uppers.size(),
nums.size()
)
);

for(size_t i = 0; i < minsize; ++i)
{
std::cout << lowers[i] << uppers[i] << nums[i] << "\n";
}
}

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);

Clojure

(doseq [s (map #(str %1 %2 %3) "abc" "ABC" "123")]
(println s))

The sequence stops when the shortest list is exhausted.

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
.

Common Lisp

Using functional application

(mapc (lambda (&rest args)
(format t "~{~A~}~%" args))
'(|a| |b| |c|)
'(a b c)
'(1 2 3))

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

Using LOOP

(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))

D

import std.stdio, std.range;

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

{{out}}

aA1
bB2
cC3

zip() allows to specify the stopping policy. On default it stops when the shortest range is exhausted (same as StoppingPolicy.shortest):

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);
}

{{out}}

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:

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);
}

Lower level code that stops at the shortest length:

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]);
}

{{out}}

aA1
bB2

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]]));

end.

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.

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]]));

E

E lacks a nice way to do this; this is [http://wiki.erights.org/wiki/Parallel_iteration 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:

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])
}

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:

for [v1, v2, v3] in zip(a1, a2, a3) {
println(v1, v2, v3)
}

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.

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
}
}

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

EchoLisp

;; looping over different sequences : infinite stream, string, list and vector
;; loop stops as soon a one sequence ends.
;; the (iota 6) = ( 0 1 2 3 4 5) sequence will stop first.

(for ((i (in-naturals 1000)) (j "ABCDEFGHIJK") (k (iota 6)) (m #(o p q r s t u v w)))
(writeln i j k m))

1000     "A"     0     o
1001     "B"     1     p
1002     "C"     2     q
1003     "D"     3     r
1004     "E"     4     s
1005     "F"     5     t

Efene

@public
run = fn () {
lists.foreach(fn ((A, B, C)) { io.format("~s~n", [[A, B, C]]) },
lists.zip3("abc", "ABC", "123"))
}

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

Ela

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

print x = do putStrLn x

print_and_calc xs = do
xss <- return xs
return \$ each print xss

print_and_calc xs ::: IO

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:

xs = zipWith3 (\x -> (x++) >> (++)) "abc" "ABC"
"123"

Elixir

'''string list:'''

l1 = ["a", "b", "c"]
l2 = ["A", "B", "C"]
l3 = ["1", "2", "3"]
IO.inspect List.zip([l1,l2,l3]) |> Enum.map(fn x-> Tuple.to_list(x) |> Enum.join end)
#=> ["aA1", "bB2", "cC3"]

'''char_list:'''

l1 = 'abc'
l2 = 'ABC'
l3 = '123'
IO.inspect List.zip([l1,l2,l3]) |> Enum.map(fn x-> Tuple.to_list(x) end)
#=> ['aA1', 'bB2', 'cC3']

When the length of the list is different:

iex(1)> List.zip(['abc','ABCD','12345']) |> Enum.map(&Tuple.to_list(&1))
['aA1', 'bB2', 'cC3']
iex(2)> List.zip(['abcde','ABC','12']) |> Enum.map(&Tuple.to_list(&1))
['aA1', 'bB2']

The zipping finishes as soon as any enumerable completes.

Elena

ELENA 4.1 :

import system'routines;
import extensions;

public program()
{
var a1 := new string[]::("a","b","c");
var a2 := new string[]::("A","B","C");
var a3 := new int[]::(1,2,3);

for(int i := 0, i < a1.Length, i += 1)
{
console.printLine(a1[i], a2[i], a3[i])
};

programUsingZip();

}

Using zipBy extension:

import system'routines.
import extensions.

public program
{
var a1 := new string[]::("a","b","c");
var a2 := new string[]::("A","B","C");
var a3 := new int[]::(1,2,3);
var zipped := a1.zipBy(a2,(first,second => first + second.toString() ))
.zipBy(a3, (first,second => first + second.toString() ));

zipped.forEach:(e)
{ console.writeLine:e };

}

{{out}}

aA1
bB2
cC3

Erlang

Shortest option:

lists:zipwith3(fun(A,B,C)->
io:format("~s~n",[[A,B,C]]) end, "abc", "ABC", "123").

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:

lists:foreach(fun({A,B,C}) ->
io:format("~s~n",[[A,B,C]]) end,
lists:zip3("abc", "ABC", "123")).

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:

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

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

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

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:

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

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.

for c1,c2,n in Seq.zip3 ['a';'b';'c'] ['A';'B';'C']
[1;2;3] do
printfn "%c%c%d" c1 c2 n

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

Factor

"abc" "ABC" "123" [ [ write1 ] tri@ nl ]
3each

Fantom

This will stop when it reaches the end of the shortest list.

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]}")
}
}
}

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
;

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

If the arrays are of different length (say, array ns has no third element), then when its turn comes the next unit of storage along from the second element will be accessed, its content interpreted as an integer, and its decimal value printed... If however, array bound checking is activated (or there is a memory access protection scheme that would detect this), a feature unavailable via many compilers and not the default on the rest, then an error will be detected and the run will be terminated, possibly with a somewhat helpful message.

If instead of reading the action had been to store a value into the array, then in the absence of bound checking, arbitrary damage will be done (to code or data) that will possibly result in something going wrong. And if you're lucky, it will happen swiftly.

FreeBASIC

' FB 1.05.0 Win64

Function min(x As Integer, y As Integer) As Integer
Return IIf(x < y, x, y)
End Function

Dim arr1(1 To 3) As String = {"a", "b", "c"}
Dim arr2(1 To 3) As String = {"A", "B", "C"}
Dim arr3(1 To 3) As Integer = {1, 2, 3}

For i As Integer = 1 To 3
Print arr1(i) & arr2(i) & arr3(i)
Next

Print

' For arrays of different lengths we would need to iterate up to the mimimm length of all 3 in order
' to  get a contribution from each one. For example:

Dim arr4(1 To 4) As String = {"A", "B", "C", "D"}
Dim arr5(1 To 2) As Integer = {1, 2}

Dim ub As Integer = min(UBound(arr1), min(UBound(arr4), UBound(arr5)))
For i As Integer = 1 To ub
Print arr1(i) & arr2(i) & arr3(i)
Next

Print
Sleep

{{out}}

aA1
bB2
cC3

aA1
bB2

FunL

import lists.zip3

for x <- zip3( ['a', 'b', 'c'], ['A', 'B', 'C'], [1, 2, 3] )
println( x.mkString() )

{{out}}

aA1
bB2
cC3

Gambas

'''[https://gambas-playground.proko.eu/?gist=3a69e733694aeab3b72c6a5c0316535b Click this link to run this code]'''

Public Sub Main()
Dim a1 As String[] = ["a", "b", "c"]
Dim a2 As String[] = ["A", "B", "C"]
Dim a3 As String[] = ["1", "2", "3"]
Dim siC As Short

For siC = 0 To a1.Max
Print a1[siC] & a2[siC] & a3[siC]
Next

End

Output:

aA1
bB2
cC3

GAP

# The Loop function will apply some function to every tuple built by
taking
# the i-th element of each list. If one of them is exhausted before the
others,
# 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;

# 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

Go

Go's "range clause" of a for statement only looks at a single iterable value (array, slice, etc). 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's philosophy is that you should explicitly check for whatever conditions are meaningful in your application and explicitly handle whatever errors are plausible.

package main

import "fmt"

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

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

Golfscript

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

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

Groovy

Solution:

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}\${it}\${it}" }
}

Test:

def x = ['a', 'b', 'c']
def y = ['A', 'B', 'C']
def z = [1, 2, 3]

synchedConcat(x, y, z).each { println it }

{{out}}

aA1
bB2
cC3

Harbour

'''Using FOR EACH ... NEXT statement'''

PROCEDURE Main()
LOCAL a1 := { "a", "b", "c" }, ;
a2 := { "A", "B", "C", "D" }, ; // the last element "D" of this array will be ignored
a3 := { 1, 2, 3 }
LOCAL e1, e2, e3

FOR EACH e1, e2, e3 IN a1, a2, a3
Qout( e1 + e2 + hb_ntos( e3 ) )
NEXT
RETURN

Output: aA1 bB2 cC3 If the arrays are not of equal length, the iteration stops after the last item of the smaller array has been processed; any extra items of lengthier arrays are ignored (or in other words, the iteration counter never exceeds the length of the smaller array, thus preventing an 'out of subscript range' error).

'''Using list comprehension'''

{-# LANGUAGE ParallelListComp #-}
main = sequence [ putStrLn [x, y, z] | x <- "abd" | y <- "ABC" | z <- "123"]

'''Using Transpose'''

In this special case of transposing strings.

import Data.List
main = mapM putStrLn \$ transpose ["abd", "ABC", "123"]

'''Using ZipWith*'''

import Data.List
main = mapM putStrLn \$ zipWith3 (\a b c -> [a,b,c]) "abc" "ABC" "123"

'''Using applicative ZipLists'''

ZipLists generalize zipWith to any number of parameters

import Control.Applicative
main = sequence \$ getZipList \$ (\x y z -> putStrLn [x, y, z]) <\$> ZipList "abd" <*> ZipList "ABC" <*> ZipList "123"

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());
}
}

HicEst

CHARACTER :: A = "abc"
REAL ::  C(3)

C = \$ ! 1, 2, 3

DO i = 1, 3
WRITE() A(i), "ABC"(i), C(i)
ENDDO

The first solution uses co-expressions to produce parallel evaluation.

procedure main()
a := create !["a","b","c"]
b := create !["A","B","C"]
c := create !["1","2","3"]
while write(@a,@b,@c)
end

The second solution is more like other procedural languages and also handles unequal list lengths.

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

{{libheader|Icon Programming Library}} [http://www.cs.arizona.edu/icon/library/procs/numbers.htm Uses max from numbers]

J

For arrays of different types:

,.&:(":"0@>)/ 'abc' ; 'ABC' ; 1 2 3
aA1
bB2
cC3

This approach works by representing the digits as characters.

Where arrays are all the same type (all numeric or all string):

,.&:>/ 'abc' ; 'ABC' ; '123'
aA1
bB2
cC3

Both of these implementations reject arrays with conflicting lengths.

Other options include:

|: 'abc', 'ABC' ,:;":&> 1 2 3
aA1
bB2
cC3
|: 'abc', 'ABC',: '123'
aA1
bB2
cC3

These implementations pad short arrays with spaces.

Or:

|:>]&.>L:_1 'abc';'ABC';<1 2 3
┌─┬─┬─┐
│a│A│1│
├─┼─┼─┤
│b│B│2│
├─┼─┼─┤
│c│C│3│
└─┴─┴─┘

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. (An "empty box" is what a programmer in another language might call "a pointer to a zero length array".)

Java

{{trans|JavaScript}}

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]);
}

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.

JavaScript

Imperative

This loops over the indices of the first array, and uses that to index into the others.

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";
}

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

Alternatively, we can nest a couple of calls to '''.forEach()''': one for the array of three arrays, and one for each of the three index positions:

var lstOut = ['', '', ''];

[["a", "b", "c"], ["A", "B", "C"], ["1", "2", "3"]].forEach(
function (a) {
[0, 1, 2].forEach(
function (i) {
// side-effect on an array outside the function
lstOut[i] += a[i];
}
);
}
);

// lstOut --> ["aA1", "bB2", "cC3"]

=ES5=

Functional options include folding across an array of arrays with the built-in '''Array.reduce()''', using a zipWith() function of suitable arity, or mapping over the output of a generic (any arity) zip() function.

(The generic zip function is the most tolerant – it simply ignores further elements in any arrays which are longer than the shortest array).

Reduce / fold:

(function (lstArrays) {

return lstArrays.reduce(
function (a, e) {
return [
a + e,
a + e,
a + e
];
}, ['', '', ''] // initial copy of the accumulator
).join('\n');

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

A fixed arity ZipWith:

(function (x, y, z) {

// function of arity 3 mapped over nth items of each of 3 lists
// (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
function zipWith3(f, xs, ys, zs) {
return zs.length ? [f(xs, ys, zs)].concat(
zipWith3(f, xs.slice(1), ys.slice(1), zs.slice(1))) : [];
}

function concat(x, y, z) {
return ''.concat(x, y, z);
}

return zipWith3(concat, x, y, z).join('\n')

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

Or we could write a generic '''zipListsWith''' applying some supplied function overs lists derived from the nth members of an arbitrary list of (equal-length) lists.

(function () {
'use strict';

// zipListsWith :: ([a] -> b) -> [[a]] -> [[b]]
function zipListsWith(f, xss) {
return (xss.length ? xss : [])
.map(function (_, i) {
return f(xss.map(function (xs) {
return xs[i];
}));
});
}

// concat :: [a] -> s
function concat(lst) {
return ''.concat.apply('', lst);
}

// TEST
return zipListsWith(
concat,
[["a", "b", "c"], ["A", "B", "C"], [1, 2, 3]]
)
.join('\n');
})();

{{Out}}

aA1
bB2
cC3

=ES6=

By transposition:

(() => {
'use strict';

// GENERIC FUNCTIONS -----------------------------------------------------

// concat :: [[a]] -> [a]
const concat = xs =>
xs.length > 0 ? (() => {
const unit = typeof xs === 'string' ? '' : [];
return unit.concat.apply(unit, xs);
})() : [];

// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) => xs.map(f);

// transpose :: [[a]] -> [[a]]
const transpose = xs =>
xs.map((_, col) => xs.map(row => row[col]));

// unlines :: [String] -> String
const unlines = xs => xs.join('\n');

// TEST ------------------------------------------------------------------
const xs = [
['a', 'b', 'c'],
['A', 'B', 'C'],
[1, 2, 3]
];

return unlines(
map(concat, transpose(xs))
);
})();

{{Out}}

aA1
bB2
cC3

jq

The following solution is based on the assumption that all the arrays can be presented as an array of arrays. This allows any number of arrays to be handled.

Specifically, zip/0 expects an array of 0 or more arrays as its input. The first array determines the number of items in the output; nulls are used for padding.

# zip/0 emits [] if input is [].

def zip:
. as \$in
| [range(0; \$in|length) as \$i | \$in | map( .[\$i] ) ];

Example 1: [["a","b","c"], ["A","B","C"], [1,2,3]] | zip {{Out}}

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

To obtain the compact output used in the the task description, we can filter the results through a "pretty-print" function: def pp: reduce .[] as \$i (""; . + "(\$i)");

Example 2: [["a","b","c"], ["A","B","C"], [1,2,3]] | zip | map(pp) {{Out}}

[
"aA1",
"bB2",
"cC3"
]

As already mentioned, the above definition of zip/0 privileges the first array, and if the subsequent arrays are of different lengths, null is used as a filler. Thus: [["a","b","c"], ["A","B"], ] | zip

produces: [["a","A",1],["b","B",null],["c",null,null]]

'''Handling jagged input''' An alternative approach would be use a variant of zip/0 that pads all arrays shorter than the longest with nulls. Here is such a variant:

# transpose a possibly jagged matrix
def transpose:
if . == [] then []
else (.[1:] | transpose) as \$t
| . as \$row
| reduce range(0; [(\$t|length), (.|length)] | max) as \$i
([]; . + [ [ \$row[\$i] ] + \$t[\$i] ])
end;

Jsish

/* Loop over multiple arrays, in Jsish */
var a1 = ['a', 'b', 'c'];
var a2 = ['A', 'B', 'C'];
var a3 = [1, 2, 3];

puts('Equal sizes');
var arr = [a1, a2, a3];
var m = arr.length;
for (var a of arr) if (a.length > m) m = a.length;
for (var i = 0; i < m; i++) printf("%q%q%q\n", a1[i], a2[i], a3[i]);

puts('\nUnequal sizes');
var a4 = [];
var a5 = [4,5,6,7];

arr = [a1, a2, a3, a4, a5];
m = arr.length;
for (a of arr) if (a.length > m) m = a.length;
for (i = 0; i < m; i++) printf("%q%q%q%q%q\n", a1[i], a2[i], a3[i], a4[i], a5[i]);

/*
=!EXPECTSTART!=
Equal sizes
aA1
bB2
cC3

Unequal sizes
aA1undefined4
bB2undefined5
cC3undefined6
/home/btiffin/forge/jsi/jsi-test/rosetta/loopOverMultipleArrays.jsi:19: warn: call with undefined var for argument arg 2 '...', in call to 'printf' <undefined>.    (at or near "%q%q%q%q%q
")

undefinedundefinedundefinedundefined7
=!EXPECTEND!=
*/

{{out}}

prompt\$ jsish -u loopOverMultipleArrays.jsi
[PASS] loopOverMultipleArrays.jsi

Julia

'''With a higher order function''':

foreach(println, ('a', 'b', 'c'), ('A', 'B', 'C'), (1, 2, 3))

'''With a loop''':

for (i, j, k) in zip(('a', 'b', 'c'), ('A', 'B', 'C'), (1, 2, 3))
println(i, j, k)
end

{{out}}

aA1
bB2
cC3

K

{,/\$x}'+("abc";"ABC";1 2 3)

{{out}}

("aA1"
"bB2"
"cC3")

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

The following is a more general approach where

&/#:'x

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

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

{{out}}

("aA1"
"bB2"
"cC3")

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

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

Kotlin

// version 1.0.6

fun main(args: Array<String>) {
val a1 = charArrayOf('a', 'b', 'c')
val a2 = charArrayOf('A', 'B', 'C')
val a3 = intArrayOf(1, 2, 3)
for(i in 0 .. 2) println("\${a1[i]}\${a2[i]}\${a3[i]}")
println()
// For arrays of different sizes we would need to iterate up to the mimimm size of all 3 in order
// to  get a contribution from each one.
val a4 = intArrayOf(4, 5, 6, 7)
val a5 = charArrayOf('d', 'e')
val minSize = Math.min(a2.size, Math.min(a4.size, a5.size))  // minimum size of a2, a4 and a5
for(i in 0 until minSize) println("\${a2[i]}\${a4[i]}\${a5[i]}")
}

{{out}}

aA1
bB2
cC3

A4d
B5e

LFE

(lists:zipwith3
(lambda (i j k)
(io:format "~s~s~p~n" `(,i ,j ,k)))
'(a b c)
'(A B C)
'(1 2 3))

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

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

Lisaac

+ 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;
};
);

LiveCode

Arrays

command loopArrays
local lowA, uppA, nums, z
put "a,b,c" into lowA
put "A,B,C" into uppA
put "1,2,3" into nums

split lowA by comma
split uppA by comma
split nums by comma

repeat with n = 1 to the number of elements of lowA
put lowA[n] & uppA[n] & nums[n] & return after z
end repeat
put z

end loopArrays

"list" processing

command loopDelimitedList
local lowA, uppA, nums, z
put "a,b,c" into lowA
put "A,B,C" into uppA
put "1,2,3" into nums

repeat with n = 1 to the number of items of lowA
put item n of lowA & item n of uppA & item n of nums
& return after z
end repeat
put z

end loopDelimitedList

Output - both behave similarly for this exercise.

aA1
bB2
cC3

When there are fewer elements than the first (or whatever the loop is based on), livecode will add an "empty" value. If we add a "d" to lowA and a 4 to nums we get the following:

aA1
bB2
cC3
d4

{{works with|UCB 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

Lua

This can be done with a simple for loop:

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

but it may be more enlightening (and in line with the spirit of the challenge) to use the generic for:

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

Mathematica

This can be done with a built-in function:

MapThread[Print, {{"a", "b", "c"}, {"A", "B", "C"}, {1, 2, 3}}];

All arguments must be lists of the same length.

Mercury

:- 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).

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

```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.

MUMPS

Pieces of String version

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

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

{{out}}

USER>d LOOPMULT^ROSETTA

aA1
bB2
cC3
dD

Local arrays version

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,%

The commented out line will throw an 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). {{out}}

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.

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");
}
}

Alternately: {{trans|C#}}

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]);
}
}

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
say ai[x_] || bi[x_] || ci[x_]
end x_

method sampleData(arg) public static returns Rexx
smp = ' '
smp = arg.words
loop i_ = 1 to smp
smp[i_] = arg.word(i_)
end i_

return smp

{{out}}

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

```

## NewLISP

```NewLISP
(map println '(a b c) '(A B C) '(1 2
3))
```

## Nim

```nim
let
a = @['a','b','c']
b = @["A","B","C"]
c = @[1,2,3]

for i in 0..2:
echo a[i], b[i], c[i]
```

Works with oo2c version 2

```oberon2

MODULE LoopMArrays;
IMPORT
Out;
VAR
x,y: ARRAY 3 OF CHAR;
z: ARRAY 3 OF INTEGER;

PROCEDURE DoLoop;
VAR
i: INTEGER;
BEGIN
i := 0;
WHILE i < LEN(x) DO
Out.Char(x[i]);Out.Char(y[i]);Out.LongInt(z[i],0);Out.Ln;
INC(i)
END
END DoLoop;

BEGIN
x := 'a';y := 'A';z := 1;
x := 'b';y := 'B';z := 2;
x := 'c';y := 'C';z := 3;
DoLoop
END LoopMArrays.

```

Output: