filter(E)

FUNKTION:
    mixed * filter(mixed *arg, string fun, string|object ob
                                         , mixed extra...)
    mixed * filter(mixed *arg, closure cl, mixed extra...)
    mixed * filter(mixed *arg, mapping map, mixed extra...)

    string  filter(string arg, string fun, string|object ob
                                      , mixed extra...)
    string  filter(string arg, closure cl, mixed extra...)
    string  filter(string arg, mapping map, mixed extra...)

    mapping filter(mapping arg, string func, string|object ob
                                           , mixed extra...)
    mapping filter(mapping arg, closure cl, mixed extra...)


PARAMETER:
    arr     - zu filterndes Array/Mapping/String
    fun/cl  - zu rufende Methode/Closure
    map     - filterndes Mapping
    ob      - Objekt/Dateiname, an dem Methode gerufen werden soll
    extra   - weitere Parameter fuer Methode/Closure

BESCHREIBUNG:        
    Ruft fuer jedes Element des Arrays oder Mappings <arg> die Funktion
    <ob>-><func>() bzw. die Closure <cl> auf und liefert jene Elemente,
    fuer die die Funktion / Closure TRUE ergeben hat. Die <extra>
    Argumente werden als zusaetzliche Parameter an die Funktion
    uebergeben und duerfen keine Referenzen von Array- oder Mapping-
    Elementen sein (wie &(i[1]) ).

    Wird <ob> nicht angegeben oder ist es weder ein String noch ein
    Objekt, wird standardmaessig this_object() verwendet.

    Ist <arg> ein Array oder struct, wird <fun> mit jedem Element des
    Arrays/der struct als ersten Parameter aufgerufen, gefolgt von den
    <extra> Argumenten. Wenn das Resultat der Funktion TRUE ergibt, wird
    das Element in das Ergebnis der filter() Operation mit einbezogen.

    Wird filter() mit einem Mapping <map> anstelle der Funktion <func>
    aufgerufen, wird jedes Element im Array <arg>, das ein Key von <map>
    ist, ins Ergebnis mit einbezogen.

    Wenn <arg> ein Mapping ist, wird die Funktion <func> mit jedem Key
    als erstem und (falls vorhanden) den Werten dieses Keys als zweitem
    Parameter, gefolgt von den <extra> Argumenten, aufgerufen. Wenn die
    Funktion TRUE ergibt, wird das betreffende Element des Mappings ins
    Ergebnis aufgenommen.

    Abhaengig von der Groesse des Mappings <arg> erfolgt der Aufruf der
    Funktion auf drei unterschiedliche Arten:

        widthof(arg) == 0: ob->func(key, 0, extra...)
                     == 1: ob->func(key, arg[key], extra...)
                      > 1: ob->func( key
                                   , ({ arg[key,0] ...arg[key,width-1] })
                                   , extra...)

    Der Vorteil dieser Vorgehensweise ist, dass beide Typen von
    multidimensionalen Mappings (Mappings mit mehreren Werte pro Key und
    Mappings aus Arrays) gleich verarbeitet werden koennen.

    Ist <arg> ein String, werden der Filterfunktion die einzelnen Zeichen
    des Strings uebergeben und nur jene Zeichen im zurueckgegebenen
    String aufgenommen, fuer die die Filterfunkton != 0 zurueckgibt.


AENDERUNGEN
    Eingefuehrt in LDMud 3.2.6. Die Funktion loest filter_array() ab.

RUeCKGABEWERT:
    Gefiltertes Array mit allen die Filterbedingung erfuellenden Elementen.

BEMERKUNGEN:
    (1) Achtung, die Elemente in 'arr' werden nicht tief kopiert, sind sie
    also selbst Arrays oder Mappings, so fuehrt eine spaetere Aenderung im
    Rueckgabe-Arrays zur Aenderung im Ursprungsarray:

    int *i, *j;
    i=({({1,2,3}),({4,5,6})});
    j=filter(i, #'sizeof);     // filtert leere Arrays heraus
    j[0][0]=8;

    fuehrt zu: i==j==({({8,2,3}),({4,5,6})});

    (2) Das Kopieren in das Rueckgabemapping erfolgt fuer jedes Element nach
    Ausfuehrung der Filtermethode. Aenderungen der Werte im Array in dieser
    Methode (globale Variable/Uebergabe als Referenz an filter)
    schlagen sich also im Rueckgabearray nieder.

    (3) Fuer Arrays wirkt filter() wie filter_array(), fuer Mappings stellt
    filter() eine Verallgemeinerung von filter_indices() dar.

BEISPIEL:
    ### Filtere alle Lebewesen in einem Raum in ein Array ###
    filter(all_inventory(this_object()),#'living);

    ### Filtere alle tauben Spieler im Raum in ein Array ###
    static int filter_isdeaf(object who) {
      return (interactive(who) && who->QueryProp(P_DEAF));
    }

    filter(all_inventory(this_object()), #'filter_isdeaf);


    ### Filtern von Idlern (>=1 Sekunde idle) ###
    // Folgend identische Resultate, aber andere Ansaetze:

    #1: nutzt die Efun query_idle() als Lfun-Closure (ideal hier)
        idle_usr = filter(users(), #'query_idle );

    #2: mit Filtermethode
        int check_if_idle(object user) {
          return query_idle(user);
        }

        #2a: filtert mittels der Lfun im selben Objekt die Idler in das
             Rueckgabearray
             idle_usr = filter(users(), "check_if_idle");
             idle_usr = filter(users(), "check_if_idle", this_object());

        #2b: ruft die Lfun check_if_idle() als Lfun-Closure (Funktions-
             pointer)
             idle_usr = filter(users(), #'check_if_idle );

    #3: Nutzt eine Inline-Closure
        idle_usr = filter(users(), function int (object user) {
                     return query_idle(user);
                   } );

    ### Filtern von Idlern (>=20 Sekunden idle) mit Extraparameter ###
    // Folgend identische Resultate, aber andere Ansaetze:

    #1: die Efun koennen wir nicht mehr direkt nutzen, weil sie
        diesen Parameter nicht unterstuetzt
       // idle_usr = filter(users(), #'query_idle );

    #2: mit separater Filtermethode ... mit neuem Parameter
        int check_if_idle(object user, int length) {
          return query_idle(user)>length;
        }

        #2a: filtert mittels der Lfun im selben Objekt die Idler in das
             Rueckgabearray ... mit drittem Parameter!
             idle_usr = filter(users(), "check_if_idle", this_object(), 20);

        #2b: ruft die Lfun check_if_idle() als Lfun-Closure (Funktions-
             pointer)
             idle_usr = filter(users(), #'check_if_idle, 20);

    #3: Nutzt eine Inline-Closure
        idle_usr = filter(users(), function int (object user, int length) {
                     return (query_idle(user) > length); 
                     }, 20);

SIEHE AUCH:
     Arrays:        map(E)
     Objektarrays:  filter_objects(E), map_objects(E)
     Mappings:      filter_indices(E), map_indices(E)
                    walk_mapping(E), member(E)

     Sonstiges:     sort_array(E), unique_array()
                    transpose_array(E)

----------------------------------------------------------------------------
23.09.2019, Zesstra
