Loop over multiple arrays simultaneously: Difference between revisions
m →{{header|C}}: space |
m Fixed lang tags. |
||
Line 9: | Line 9: | ||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
<lang Ada> |
<lang Ada>with Ada.Text_IO; use Ada.Text_IO; |
||
with Ada.Text_IO; use Ada.Text_IO; |
|||
procedure Array_Loop_Test is |
procedure Array_Loop_Test is |
||
Line 21: | Line 20: | ||
Put_Line (A1 (Index) & A2 (Index) & Integer'Image (A3 (Index))(2)); |
Put_Line (A1 (Index) & A2 (Index) & Integer'Image (A3 (Index))(2)); |
||
end loop; |
end loop; |
||
end Array_Loop_Test; |
end Array_Loop_Test;</lang> |
||
⚫ | |||
=={{header|C}}== |
=={{header|C}}== |
||
Line 118: | Line 116: | ||
=={{header|Clojure}}== |
=={{header|Clojure}}== |
||
⚫ | |||
<lang clojure> |
|||
⚫ | |||
⚫ | |||
⚫ | |||
</lang> |
|||
The sequence stops when the shortest list is exhausted. |
The sequence stops when the shortest list is exhausted. |
||
Line 135: | Line 131: | ||
=={{header|D}}== |
=={{header|D}}== |
||
This code snippet will clamp to the array of the shortest length |
This code snippet will clamp to the array of the shortest length |
||
⚫ | |||
<lang d> |
|||
⚫ | |||
int[]arr3 = [1,2,3]; |
int[]arr3 = [1,2,3]; |
||
foreach(i,ele;arr1) { |
foreach(i,ele;arr1) { |
||
Line 143: | Line 138: | ||
} |
} |
||
std.writefln("%s",""~ele~arr2[i]~std.string.toString(arr3[i])); |
std.writefln("%s",""~ele~arr2[i]~std.string.toString(arr3[i])); |
||
⚫ | |||
} |
|||
</lang> |
|||
=={{header|E}}== |
=={{header|E}}== |
||
Line 201: | Line 195: | ||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
Shortest option: |
Shortest option: |
||
⚫ | |||
<lang erlang> |
|||
⚫ | |||
</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. |
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 <tt>lists:foreach/2</tt>, which also guarantees evaluation order: |
The technically cleanest way to do things would be with <tt>lists:foreach/2</tt>, which also guarantees evaluation order: |
||
⚫ | |||
<lang erlang> |
|||
⚫ | |||
⚫ | |||
⚫ | |||
</lang> |
|||
If the lists are not all the same length, an error is thrown. |
If the lists are not all the same length, an error is thrown. |
||
Line 247: | Line 237: | ||
=={{header|J}}== |
=={{header|J}}== |
||
<lang j>(,.":"0)&:>/ 'abc' ; 'ABC' ; 1 2 3</lang> |
|||
This implementation rejects arrays with conflicting lengths. |
This implementation rejects arrays with conflicting lengths. |
||
Line 271: | Line 261: | ||
=={{header|Lisaac}}== |
=={{header|Lisaac}}== |
||
<lang Lisaac> |
<lang Lisaac>Section Header |
||
Section Header |
|||
+ name := ARRAY_LOOP_TEST; |
+ name := ARRAY_LOOP_TEST; |
||
Line 298: | Line 287: | ||
'\n'.print; |
'\n'.print; |
||
}; |
}; |
||
); |
);</lang> |
||
</lang> |
|||
=={{header|Logo}}== |
=={{header|Logo}}== |
||
{{works with|UCB Logo}} |
{{works with|UCB Logo}} |
||
⚫ | |||
<lang logo> |
|||
⚫ | |||
(foreach [a b c] [A B C] [1 2 3] [print (word ?1 ?2 ?3)]) ; as above, one per line |
(foreach [a b c] [A B C] [1 2 3] [print (word ?1 ?2 ?3)]) ; as above, one per line</lang> |
||
</lang> |
|||
=={{header|Modula-3}}== |
=={{header|Modula-3}}== |
||
Line 399: | Line 385: | ||
NEXT |
NEXT |
||
CLOSE |
CLOSE |
||
END FUNCTION |
END FUNCTION</lang> |
||
</lang> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
Line 408: | Line 393: | ||
bB2 |
bB2 |
||
cC3 |
cC3 |
||
>>> |
>>></lang> |
||
If lists are different lengths, <tt>zip()</tt> stops after the shortest one. |
If lists are different lengths, <tt>zip()</tt> stops after the shortest one. |
||
Line 416: | Line 401: | ||
bB2 |
bB2 |
||
cC3 |
cC3 |
||
>>> |
>>></lang> |
||
If lists are different lengths, <tt>map()</tt> pretends that the shorter lists were extended with <tt>None</tt> items. |
If lists are different lengths, <tt>map()</tt> pretends that the shorter lists were extended with <tt>None</tt> items. |
||
Line 436: | Line 421: | ||
#D4 |
#D4 |
||
##5 |
##5 |
||
>>> |
>>></lang> |
||
(The Python 2.X equivalent is itertools.izip_longest) |
(The Python 2.X equivalent is itertools.izip_longest) |
||
=={{header|R}}== |
=={{header|R}}== |
||
<lang R> |
<lang R>multiloop <- function(...) |
||
multiloop <- function(...) |
|||
{ |
{ |
||
# Retrieve inputs and convert to a list of character strings |
# Retrieve inputs and convert to a list of character strings |
||
Line 461: | Line 445: | ||
} |
} |
||
} |
} |
||
multiloop(letters[1:3], LETTERS[1:3], 1:3) |
multiloop(letters[1:3], LETTERS[1:3], 1:3)</lang> |
||
</lang> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
Line 483: | Line 466: | ||
Compute the transpose of the list formed of the three lists. |
Compute the transpose of the list formed of the three lists. |
||
If they're of unequal lengths, an exception occurs. |
If they're of unequal lengths, an exception occurs. |
||
<lang Ursala> |
<lang Ursala>#show+ |
||
#show+ |
|||
main = ~&K7 <'abc','ABC','123'> |
main = ~&K7 <'abc','ABC','123'></lang> |
||
</lang> |
|||
output: |
output: |
||
<pre> |
<pre> |
Revision as of 21:30, 20 November 2009
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
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.
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>
C
Implemented to print from a list of lists. <lang c>#include <stdio.h>
typedef struct closure {
void (*f)( void *elem, void *data); void *data;
} *Closure;
typedef struct listSpec{
void (*print)( void *); void *ary; int count; short elem_size;
} *ListSpec;
- 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( int *ival) { printf("%3d,", *ival); } int ary1[] = { 6,5,4,9,8,7 }; struct listSpec lspec1 = LIST_SPEC( &PrintInt, int, ary1 );
void PrintShort( short *ival) { printf("%3d,", *ival); } short ary2[] = { 3, 66, 20, 15, 7, 22, 10 }; struct listSpec lspec2 = LIST_SPEC( &PrintShort , short, ary2 );
void PrintStrg( char **strg ) { printf(" %s", *strg); } char *ary3[] = {"Hello", "all", "you","good", "folks","out", "there" }; struct listSpec lspec3 = LIST_SPEC( &PrintStrg , char *, ary3 );
void PrintLstSpec( 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>
Clojure
<lang lisp>(doseq [s (map #(str %1 %2 %3) "abc" "ABC" "123")]
(println s))</lang>
The sequence stops when the shortest list is exhausted.
Common Lisp
<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.
D
This code snippet will clamp to the array of the shortest length <lang d>char[]arr1 = "abc",arr2 = "ABC"; int[]arr3 = [1,2,3]; foreach(i,ele;arr1) {
if (i == arr2.length || i == arr3.length) { break; } std.writefln("%s",""~ele~arr2[i]~std.string.toString(arr3[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.)
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.
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>package;
import neko.Lib;
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) Lib.println(a[i] + b[i] + c[i].string()); } }</lang>
J
<lang j>(,.":"0)&:>/ 'abc' ; 'ABC' ; 1 2 3</lang>
This implementation rejects arrays with conflicting lengths.
Java
<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 one array is too "short", an ArrayIndexOutOfBoundException
will be thrown.
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"]; var b = ["A","B","C"]; var c = [1,2,3]; var output = ""; for (var i in a) {
output += a[i] + b[i] + c[i] + "\n";
}</lang> If one array is too "short", you will see the string "undefined" appear in the output.
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>
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>
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>
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 al =
match al with | [] -> () | x::xs -> let len = Array.length x in let b = List.fold_left (fun b a -> b && (Array.length a = len)) true xs in if not b then raise(Invalid_argument "n_arrays_iter: arrays of different length"); for i = 0 to pred len do let ai = List.map (fun a -> a.(i)) al in let () = f ai in () 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>
Perl 6
<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.
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>
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() pretends that the shorter lists were extended with None items.
Using itertools.imap(): <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:<lang python>>>> from itertools import zip_longest >>> print ( '\n'.join(.join(x) for x in zip_longest('abc', 'ABCD', '12345', fillvalue='#')) ) aA1 bB2 cC3
- D4
- 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>
Ruby
<lang ruby>['a','b','c'].zip(['A','B','C'], [1,2,3]).each {|i,j,k| puts "#{i}#{j}#{k}"}</lang>
or
<lang ruby>['a','b','c'].zip(['A','B','C'], [1,2,3]).each {|a| puts a.join()}</lang>
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.
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."
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