Filter

From Rosetta Code
Revision as of 19:55, 8 August 2007 by Mt (talk | contribs) (→‎[[Prolog]]: use findall/3, =:=/2 - now also works for D == [])
Task
Filter
You are encouraged to solve this task according to the task description, using any language you may know.

Select certain elements from an Array into a new Array in a generic way. To demonstrate, select all even numbers from an Array.

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;

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

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

C++

Compiler: Visual C++ 2005

Libraries: STL, 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

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

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}

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)


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

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

Haskell

 ary = [1..10]
 evens = [ x | x <- ary, even x ]

IDL

The where() function can select elements on any logical expression. For example

 result = array[where(NOT array AND 1)]

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

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

Interpreter: Firefox 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)];

Perl

 my @list = (1, 2, 3, 4, 5, 6);
 my @even = grep { 0 == $_%2; } @list;

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

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

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]

Python

values = range(10)
evens = [x for x in values if not(x & 1)]
ievens = (x for x in values if not(x & 1)) # lazy

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]

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;

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


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.

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

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;

Standard ML

 val ary = [1,2,3,4,5,6];
 List.filter (fn x => x mod 2 = 0) ary

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

Toka

 10 cells is-array table
 10 cells is-array even
 {
   variable source
   [ swap source ! >r reset r>
     [ i source @ get-element
       dup 2 mod 0 <> [ drop ] ifTrue 
     ] iterate
     depth [ i even put-element ] +iterate
   ]
 } is copy-even
 10 [ i i table put-element ] iterate
 table 10 copy-even