Select from Array
From Rosetta Code
Programming Task
This is a programming task. It lays out a problem which Rosetta Code users are encouraged to solve, using languages they know.
Select certain elements from an Array into a new Array in a generic way. To demonstrate, select all even numbers from an Array.
[edit] Ada
with Ada.Integer_Text_Io; use Ada.Integer_Text_Io; with Ada.Text_Io; use Ada.Text_Io; procedure Array_Selection is type Array_Type is array (Positive range <>) of Integer; Null_Array : Array_Type(1..0); function Evens (Item : Array_Type) return Array_Type is begin if Item'Length > 0 then if Item(Item'First) mod 2 = 0 then return Item(Item'First) & Evens(Item((Item'First + 1)..Item'Last)); else return Evens(Item((Item'First + 1)..Item'Last)); end if; else return Null_Array; end if; end Evens; procedure Print(Item : Array_Type) is begin for I in Item'range loop Put(Item(I)); New_Line; end loop; end Print; Foo : Array_Type := (1,2,3,4,5,6,7,8,9,10); begin Print(Evens(Foo)); end Array_Selection;
Here is a non-recursive solution:
with Ada.Text_IO; use Ada.Text_IO; procedure Array_Selection is type Array_Type is array (Positive range <>) of Integer; function Evens (Item : Array_Type) return Array_Type is Result : Array_Type (1..Item'Length); Index : Positive := 1; begin for I in Item'Range loop if Item (I) mod 2 = 0 then Result (Index) := Item (I); Index := Index + 1; end if; end loop; return Result (1..Index - 1); end Evens; procedure Put (Item : Array_Type) is begin for I in Item'range loop Put (Integer'Image (Item (I))); end loop; end Put; begin Put (Evens ((1,2,3,4,5,6,7,8,9,10))); New_Line; end Array_Selection;
[edit] AppleScript
set array to {1, 2, 3, 4, 5}
set evens to {}
repeat with i in array
-- very important -- list index starts at 1 not 0
if (i mod 2 = 0) then set evens to evens & i
end repeat
[edit] C
int arr[5] = {1,2,3,4,5};
int *result;
int memoryReqd = 0,length = sizeof(arr)/sizeof(arr[0]), i,j;
for (i=0; i<length; i++)
{
if(0 == arr[i]%2)
{
memoryReqd++;
}
}
result = (int*)malloc(memoryReqd*sizeof(int));
for(i=0,j=0; i<length; i++)
{
if(0 == arr[i]%2)
{
result[j++]=arr[i];
}
}
Test our resultant array:
for(i=0; i<memoryReqd; i++)
{
printf("%d\n",result[i]);
}
[edit] C++
Works with: Visual C++ version 2005
Library: STL
Library: Boost.Lambda
using namespace std; using namespace boost::lambda; vector<int> ary(10); int i = 0; for_each(ary.begin(), ary.end(), _1 = ++var(i)); // init array vector<int> evens; remove_copy_if(ary.begin(), ary.end(), back_inserter(evens), _1 % 2); // filter copy
[edit] C#
// .NET 1.x solution
ArrayList array = new ArrayList( new int[] { 1, 2, 3, 4, 5 } );
ArrayList evens = new ArrayList();
foreach( int i in array )
{
if( (i%2) == 0 )
evens.Add( i );
}
foreach( int i in evens )
System.Console.WriteLine( i.ToString() );
// .NET 2.0 solution
List<int> array = new List<int>( new int[] { 1, 2, 3, 4, 5 } );
List<int> evens = array.FindAll( delegate( int i ) { return (i%2)==0; } );
foreach( int i in evens )
System.Console.WriteLine( i.ToString() );
[edit] Clean
The standard environment is required for list and array comprehensions. We specify the types of the functions because array comprehensions are overloaded. Clean provides lazy, strict, and unboxed arrays.
module SelectFromArray import StdEnv
Create a lazy array where each element comes from the list 1 to 10.
array :: {Int}
array = {x \\ x <- [1 .. 10]}
Create (and print) a strict array where each element (coming from another array) is even.
Start :: {!Int}
Start = {x \\ x <-: array | isEven x}
[edit] Clojure
;; range and filter create lazy seq's (filter even? (range 0 100)) ;; vec will convert any type of seq to an array (vec (filter even? (vec (range 0 100))))
[edit] Common Lisp
Common Lisp has many ways of accomplishing this task. Most of them involve higher-order sequence functions that take a predicate as the first argument and a list as the second argument. A predicate is a function that returns a boolean. The higher-order functions call the predicate for each element in list, testing the element.
In this example, the goal is to find the even numbers. The most straight-forward function is to use remove-if-not, which removes elements from the list that does not pass the predicate. The predicate, in this case, tests to see if an element is even. Therefore, the remove-if-not acts like a filter:
(remove-if-not #'evenp '(1 2 3 4 5 6 7 8 9 10)) > (2 4 6 8 10)
However, this function is non-destructive, meaning the function creates a brand new list. This might be too prohibitive for very large lists. There is a destructive version that modifies the list in-place:
(delete-if-not #'evenp '(1 2 3 4 5 6 7 8 9 10)) > (2 4 6 8 10)
[edit] D
Library: Tango
import tango.core.Array; import tango.io.Stdout; void main() { auto array = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; // removeIf places even elements at the beginnig of the array and returns number of found evens auto evens = array.removeIf( ( typeof(array[0]) i ) { return (i % 2) == 1; } ); Stdout("Evens - ")( array[0 .. evens] ).newline; // The order of even elements is preserved Stdout("Odds - ")( array[evens .. $].sort ).newline; // Unlike odd elements }
Output:
Evens - [ 2, 4, 6, 8, 10 ] Odds - [ 1, 3, 5, 7, 9 ]
[edit] Erlang
Numbers = lists:seq(1, 5). EvenNumbers = lists:filter(fun (X) -> X rem 2 == 0 end, Numbers).
Or using a list comprehension:
EvenNumbers = [X || X <- Numbers, X rem 2 == 0].
[edit] Forth
: sel ( dest 0 test src len -- dest len )
cells over + swap do ( dest len test )
i @ over execute if
i @ 2over cells + !
>r 1+ r>
then
cell +loop drop ;
create nums 1 , 2 , 3 , 4 , 5 , 6 ,
create evens 6 cells allot
: .array 0 ?do dup i cells + @ . loop drop ;
: even? ( n -- ? ) 1 and 0= ;
evens 0 ' even? nums 6 sel .array \ 2 4 6
[edit] Groovy
def evens = [1, 2, 3, 4, 5].findAll{it % 2 == 0}
[edit] Haskell
In Haskell, a list is often more basic than an array:
ary = [1..10] evens = [x | x <- ary, even x]
or
evens = filter even ary
To do the same operation on an array, the simplest way it to convert it lazily into a list:
import Data.Array ary = listArray (1,10) [1..10] evens = listArray (1,n) l where n = length l l = [x | x <- elems ary, even x]
Note that the bounds must be known before creating the array, so the temporary list will be fully evaluated before the array is created.
[edit] IDL
The where() function can select elements on any logical expression. For example
result = array[where(NOT array AND 1)]
[edit] J
] v=: 20 ?@$ 100 NB. random vector 63 92 51 92 39 15 43 89 36 69 40 16 23 2 29 91 57 43 55 22 v #~ -.2|v 92 92 36 40 16 2 22
With any verb f that returns a boolean for each element of a vector v, the following is the generic solution:
(#~f) v
[edit] Java
int[] array = new int[] {1, 2, 3, 4, 5 };
List<Integer> evensList = new ArrayList<Integer>();
for (int i: array) {
if (i % 2 == 0) evensList.add(i);
}
int[] evens = evensList.toArray(new int[0]);
[edit] JavaScript
var arr = [1,2,3,4,5];
var evens = [];
for (var i=0, ilen=arr.length; i<ilen; i++)
if (arr[i] % 2 == 0)
evens.push(arr[i]);
Works with: Firefox version 2.0
var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var evens = [i for (i in numbers) if (i % 2 == 0)];
function range(limit) {
for(var i = 0; i < limit; i++) {
yield i;
}
}
var evens2 = [i for (i in range(100)) if (i % 2 == 0)];
Library: Functional
Functional.select("+1&1", [1,2,3,4]) // [2, 4]
[edit] Logo
to even? :n output equal? 0 modulo :n 2 end show filter "even? [1 2 3 4] ; [2 4]
show filter [equal? 0 modulo ? 2] [1 2 3 4]
[edit] MAXScript
arr = #(1, 2, 3, 4, 5, 6, 7, 8, 9) newArr = for i in arr where (mod i 2 == 0) collect i
[edit] Nial
filter (= [0 first, mod [first, 2 first] ] ) 0 1 2 3 4 5 6 7 8 9 10 =0 2 4 6 8 10
[edit] OCaml
It is easier to do it with a list:
let lst = [1;2;3;4;5;6] let even_lst = List.filter (fun x -> x mod 2 = 0) lst
[edit] Oz
It is easier to do it with a list:
Lst = [1 2 3 4 5]
LstEven = {Filter Lst fun{$ X} X mod 2 == 0 end}
[edit] Perl
my @list = (1, 2, 3, 4, 5, 6);
my @even = grep { 0 == $_%2; } @list;
[edit] PHP
Using a standard loop
$arr = range(1,5);
$evens = array();
foreach ($arr as $val){
if ($val % 2 == 0) $evens[] = $val);
}
print_r($evens);
Using a filter function
function is_even($var) { return(!($var & 1)); }
$arr = range(1,5);
$evens = array_filter($arr, "is_even");
print_r($evens);
[edit] Pop11
Most natural solution in Pop11 would probably use list. Below we accumulate filtered elements on the stack and then allocate array for the result:
;;; Generic filtering procedure which selects from ar elements
;;; satisfying pred
define filter_array(ar, pred);
lvars i, k;
stacklength() -> k;
for i from 1 to length(ar) do
;;; if element satisfies pred we leave it on the stack
if pred(ar(i)) then ar(i) endif;
endfor;
;;; Collect elements from the stack into a vector
return (consvector(stacklength() - k));
enddefine;
;;; Use it
filter_array({1, 2, 3, 4, 5},
procedure(x); not(testbit(x, 0)); endprocedure) =>
[edit] Prolog
evens(D, Es) :- findall(E, (member(E, D), E mod 2 =:= 0), Es).
Usage:
?- evens([1,2,3,4,5,6,7,8,9,10],E). E = [2, 4, 6, 8, 10]
[edit] Python
Works with: Python version 2.4
values = range(10) evens = [x for x in values if not x & 1] ievens = (x for x in values if not x & 1) # lazy
Alternative using the slice syntax with its optional "stride" expression:
values = range(10) evens = values[::2]
This works for all versions of Python (at least as far back as 1.5). Lists (arrays) can be "sliced" by indexing them with a range (lower and upper bounds). Thus mylist[1:9] evaluates into a list from the second item (excluding the first item which is mylist[0], of course) up to but not including the ninth item. In Python the expression mylist[:] is synonymous with mylist[0:len(mylist)] ... returning a copy of the complete list. also mylist[:x] returns the first x items from the list and negative numbers can be used such that mylist[-x:] returns the last x items from the list. The relatively obscure and optional stride expression can skip items and/or force the evaluation from the end of the list downward towards it's lower elements. Thus mylist[::-1] returns a reversed copy of the list, mylist[::2] returns all even elements, mylist[1::2] returns all odd elements, and so on.
Since strings in Python can be treated as a sort of immutable list of characters then the slicing and extended slicing can also be used with them as well. Thus mystring[::-2] will return every other character from the reverse order of the string.
Oddly enough one can also assign to a slice (of a list or other mutable indexed object. Thus the following:
values = range(10) values[::2] = [11,13,15,17,19] print values 11, 1, 13, 3, 15, 5, 17, 7, 19, 9
[edit] Raven
[ 0 1 2 3 4 5 6 7 8 9 ] as nums
group nums each
dup 1 & if drop
list as evens
[edit] Ruby
ary = [1,2,3,4,5,6] #or ary = (1..6).to_a
even_ary = ary.select{|el|el%2==0}
# => [2, 4, 6]
[edit] Seed7
var array integer: arr is [] (1, 2, 3, 4, 5); var array integer: evens is 0 times 0; var integer: number is 0;
for number range arr do
if not odd(number) then
evens &:= [] (number);
end if;
end for;
[edit] Scala
val a = Array(1, 2, 3, 4, 5)
val even = a.filter{x => x % 2 == 0}
Or
val even = for(val x <- a; x % 2 == 0) yield x
[edit] Smalltalk
#(1 2 3 4 5) select: [:number | number even]
[edit] SQL
Task: Select certain elements from an Array into a new Array in a generic way. To demonstrate, select all even numbers from an Array.
Works with: MS SQL
--Create the original array (table #nos) with numbers from 1 to 10 create table #nos (v int) declare @n int set @n=1 while @n<=10 begin insert into #nos values (@n) set @n=@n+1 end --Select the subset that are even into the new array (table #evens) select v into #evens from #nos where v % 2 = 0 -- Show #evens select * from #evens -- Clean up so you can edit and repeat: drop table #nos drop table #evens
'Works with: MySQL
create temporary table nos (v int); insert into nos values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); create temporary table evens (v int); insert into evens select v from nos where v%2=0; select * from evens order by v; /*2,4,6,8,10*/ drop table nos; drop table evens;
Or to be shorter, you could create the table evens directly from the query result :
create temporary table evens select * from nos where v%2=0;
[edit] Standard ML
val ary = [1,2,3,4,5,6]; List.filter (fn x => x mod 2 = 0) ary
[edit] Tcl
TCL doesn't really have a concept of a "number" per se - strictly speaking its only data type is the string (but a string can be interpreted as a number, of course). The generic way of getting certain elements from an array looks roughly like this:
foreach key [array names arr] {if { <condition> } then {puts $arr($key)}}
[edit] Toka
10 cells is-array table
10 cells is-array even
{
variable source
[ swap source ! >r reset r> 0
[ i source @ array.get
dup 2 mod 0 <> [ drop ] ifTrue
] countedLoop
depth 0 swap [ i even array.put ] countedLoop
]
} is copy-even
10 0 [ i i table array.put ] countedLoop
table 10 copy-even
[edit] UnixPipes
yes \ | cat -n | while read a; do ; expr $a % 2 >/dev/null && echo $a ; done
[edit] V
[even? dup 2 / >int 2 * - zero?].
[1 2 3 4 5 6 7 8 9] [even?] filter =[2 4 6 8]
Categories: Programming Tasks | Basic language learning | Ada | AppleScript | C | C++ | STL | Boost.Lambda | C sharp | Clean | Clojure | Common Lisp | D | Tango | Erlang | Forth | Groovy | Haskell | IDL | J | Java | JavaScript | Functional | Logo | MAXScript | Nial | OCaml | Oz | Perl | PHP | Pop11 | Prolog | Python | Raven | Ruby | Seed7 | Scala | Smalltalk | SQL | Standard ML | Tcl | Toka | UnixPipes | V

