Re

Reduce ebben a kurzusban: jq

2 feladat

A(z) Reduce fogalomról

Tegyük fel, hogy egy számtömb összegét szeretnénk kiszámítani. Ezt a célt többféleképpen is el lehet érni.

  • Sok nyelvben ezt a problémát egy ciklussal és egy akkumulátorváltozóval fejezik ki.

  • Ez a probléma rekurzív függvényként is megírható. Pszeudokódban valahogy így nézhet ki.

    function Add(X, Sum=0):
      if X is empty then
        return Sum
      else
        return Add(rest(X), Sum + first(X))
      end
    end
    

    Ez a módszer, amellyel a problémát kisebb darabokra bontjuk, úgy is leírható, mint „redukálás az alapeset felé”.

A reduce arra szolgál, hogy egy adatszerkezet összes elemét egyetlen értékké alakítsa. A folyamat végigiterál az adatszerkezeten, és minden elemre alkalmaz egy függvényt, hogy frissítse az akkumulált eredményt.

A jq-ban ezt a folyamatot a reduce szűrő valósítja meg. Más nyelvekben ezt „fold”, „fold-left”, „inject” vagy „aggregate” néven ismerhetik.

A jq reduce kifejezés így néz ki.

reduce STREAM_EXPRESSION as $var (INITIAL_VALUE; UPDATE_EXPRESSION)
  • A STREAM_EXPRESSION egy stream, amelynek elemei sorra a $var változóba kerülnek.
  • Az INITIAL_VALUE az akkumulált eredmény kezdőértéke (ezt nevezik „akkumulátornak”).
  • Az UPDATE_EXPRESSION összekombinálja („belehajtja”) az aktuális értéket ($var) az akkumulátorba.
    • Ebben a kifejezésben a . az akkumulátor értéke.
    • A kifejezés kimenete az akkumulátorba kerül, hogy a következő iterációban felhasználható legyen.
    • Az utolsó iteráció után az akkumulált eredmény lesz a reduce kimenete.

Nézzünk egy példát: adjuk össze egy tömb elemeit. Az add szűrő pontosan ezt teszi, de most megnézzük, hogyan lehet megvalósítani.

Ha a [10, 20, 30, 40] tömböt adjuk meg bemenetként, és nullát veszünk kezdeti állapotnak, akkor az egyes lépések így néznek ki.

# állapot elem redukáló eredmény
1 0 10 0 + 10 10
2 10 20 10 + 20 30
3 30 30 30 + 30 60
4 60 40 60 + 40 100

A jq szintaxisban ez a kód így néz ki:

0 + 10 | . + 20 | . + 30 | . + 40

Ezt kifejezhetjük a reduce szűrővel.

[10, 20, 30, 40] | reduce .[] as $n (0; . + $n)     # => 100
Note

A beépített add valójában a reduce szűrővel van megvalósítva, de a „null” értéket használja kezdeti állapotként (a nullhoz bármilyen adattípus hozzáadható).

def add: reduce .[] as $x (null; . + $x);

Néhány dolog, amit érdemes szem előtt tartani

  • A redukáló kifejezésben a . az akkumulátor. Ha a bemenet egy olyan objektum, amelyre a redukáló függvényben hivatkoznod kell, el kell tárolnod egy változóban.

    {"apple": 10, "banana": 16, "carrot": 4}
    | . as $obj
    | reduce (keys | .[]) as $key (0; . + $obj[$key])     # => 30
    
  • Az akkumulátor bármilyen adattípusú lehet. Például előfordulhat, hogy meg akarsz fordítani egy tömböt.

    ["A", "B", "C", "D"]
    | reduce .[] as $elem ([]; [$elem] + .)       # => ["D", "C", "B", "A"]
    
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg

Tanuld meg a(z) Reduce fogalmat

A gyakorlás zárolva

Oldj fel még 3 feladatot, hogy gyakorolhasd a(z) Reduce fogalmat