ugrás a tartalomhoz

Rekurzió

mahoo · 2019. Jan. 3. (Cs), 22.45
Lenne egy egyszerű feladat: nested tömbben megszámolni egy adott elem gyakoriságát, rekurzív módon.
Nekem van egy megoldásom, de nem igazán tetszik és érdekelne más megoldás.
function countItems(arr, item) {
  var result = 0;

  (function count(arr, item){
    for (var i=0; i<arr.length; i++){
      if (Array.isArray(arr[i])){
        count(arr[i], item);
      } else if (arr[i] === item) {
        result++;
      }
    }
  })(arr, item);

  return result;
}


var arr = [
	["banana", "strawberry", "apple", ["banana", "strawberry", "apple", ["apple"]], "apple"], 
  "apple",
  ["banana", "strawberry", "apple", ["banana", "strawberry", "apple"]]
];
console.log(countItems(arr, "apple"));
Ami nem tetszik:
- van benne egy 'for'
- biztos van szebb megoldas :)
 
1

L'art pour L'art

vbence · 2019. Jan. 4. (P), 00.45
Csak a nulladik elemre vizsgálsz, a szkript magát hívja a maradék elemekkel - array_slice($arr,1). Értelme nem sok van, de van benne egy kis funckionális életérzés.

Also.. a külső szkópban lévő counter nem túl szép, miért nem a függvény eredménye?
4

Lehet, hogy felreertelek, de

mahoo · 2019. Jan. 4. (P), 09.10
Lehet, hogy felreertelek, de sztem nem csak 0. elemre vizsgalok. Pl. ha a 0. elem nem tomb, akkor mar a kovetkezo indexet vizsgalom.
Megmutatnad, hogy hogyan tudom elhagyni a kulso szkopban levo valtozot? Koszi!
11

slice

vbence · 2019. Jan. 5. (Szo), 16.37
Erre gondoltam... ha szigorúan elméleti a kérdés. A kód ugyan tail-call optimizálható, ennek ellenére a krómómban out of memoryval elszáll egyillió elemnél.

function cnt(arg, subject) {
	if (arg.constructor === Array) {
		return cnt(arg[0], subject) + (arg.length > 1 ? cnt(arg.slice(1), subject) : 0);
    } else {
		return arg == subject ? 1 : 0;
    }
}

var arr = [  
    ["banana", "strawberry", "apple", ["banana", "strawberry", "apple", ["apple"]], "apple"],
  "apple",
  ["banana", "strawberry", "apple", ["banana", "strawberry", "apple"]]  
];

console.log(cnt(arr, "apple"));
12

Nincs már benne TCO: link

inf · 2019. Jan. 5. (Szo), 20.46
Nincs már benne TCO: link
13

Nem követem

vbence · 2019. Jan. 5. (Szo), 22.11
Egy ideje nem követem a JS enginek fejlődését. Csak onnan jövök, hogy 2019-ben egy neyelvben illene :D
14

Hát én inkább

inf · 2019. Jan. 6. (V), 01.11
Hát én inkább visszafejlődésnek hívnám. A legnagyobb gond nem is ez, mert vissza lehet csinálni bármikor, hanem amit a nyelvvel tettek a szabványban. Siralmas... Igazából vegyesek az érzéseim, mert ténylegesen jelen lévő problémákat próbáltak orvosolni, csak a dolog megragadt azon a szinten, hogy megnéztek más nyelveket, aztán ahol találtak egy működő megoldást, azt berántották a js syntax-ba. Pl gond volt, hogy `function(){...}.bind(this)`-t írtál sok helyen, a CoffeScript-ben erre megoldás volt az arrow function: `() => {}`. Fogták, egy az egyben beemelték a js syntax-ba, amitől az ilyen krix-krax teljesen idegen, mert mindent kulcsszavakkal ír le. Ugyanez történt a spread-el és a rest-el is, mindkettő `...` lett. Aztán volt, hogy a C-n nevelkedett embereknek nem tetszett, hogy itt nem block level scoping van, úgyhogy `var` helyett előrántották a `let` és `const` kulcsszavakat és máris az lett, amikor az előző megoldással az ég világon semmi gond nem volt azon kívül, hogy néhányan lusták voltak megtanulni, hogy ez a nyelv más, mint amit megszoktak. Gyakorlatilag most már ott tartunk, hogy az eredeti nyelvből alig maradt valami, és bár világ életemben utáltam a transpiler-eket, lassan elgondolkodok, hogy írok egy sajátot hozzá... Talán az async-await az egyetlen, amire azt mondom, hogy elfogadható, de az sincs teljesen végiggondolva.
2

reduce + closure

Endyl · 2019. Jan. 4. (P), 00.49
function getCounterReducer(search) {
  return function counterReducer(value, item) {
    if (Array.isArray(item)) {
        return item.reduce(counterReducer, value);
    }
    else if (search === item) {
        return ++value;
    }
  };
}
var count = arr.reduce(getCounterReducer('apple'), 0);
Bár azt nem értem, mi a baj a for ciklussal (vagy itt használhatnál for of ciklust is).
3

Jó ez így. Modernebb js-nél

inf · 2019. Jan. 4. (P), 09.02
Jó ez így. Modernebb js-nél for-of, amit használnak, akkor nem kell az i++ meg hasonlók bele. Lehet még array.forEach-el, esetleg még array.reduce-al is, azok valamivel lassabbak, ha sok elem van benne. Esetleg még körül lehetne nézni, hogy vannak e direkt erre nested iteratorok, de nem hiszem, hogy lennének, ha meg te magad írod js-ben, akkor az lassabb lesz a fentieknél, és igazi előnyt nem nyújt.

Ha adatbázisban csinálod, akkor ilyesmi ajánlott inkább: http://weblabor.hu/cikkek/hierarchikusadatkezeles1
5

Igen, nem ES6-os megoldasra

mahoo · 2019. Jan. 4. (P), 09.12
Igen, nem ES6-os megoldasra szerettem volna kihegyezni a kerdest.
6

Miert kell ennyire a rekurziv

MadBence · 2019. Jan. 4. (P), 15.06
Miert kell ennyire a rekurziv megoldas?

function count(arr, item) {
  if (arr === item) return 1;
  if (!Array.isArray(arr) || arr.length === 0) return 0;
  return count(arr[0], item) + count(arr.slice(1), item);
}
Masik variacio:

function count(arr, item, cnt = 0) {
  if (arr === item) return cnt + 1;
  if (!Array.isArray(arr)) return cnt;
  if (arr.length === 0) return cnt;
  return count(arr.slice(1), item, count(arr[0], item, cnt));
}
Egy sima ciklussal szerintem elegansabb, es olvashatobb:

function count(arr, item) {
  let cnt = 0;
  for (const el of arr) {
    if (el === item) cnt++;
    if (Array.isArray(el)) cnt += count(el, item);
  }
  return cnt;
}
Ha nagyon funkcionalis megkozelitesre van szukseg:

const count = (arr, item) => arr.reduce((cnt, el) => (el === item ? 1 : Array.isArray(el) ? count(el, item) : 0) + cnt, 0);
Persze inkabb erdemes reszproblemakra szetszedni, es ugy megoldani:

const flatten = arr => arr.reduce((arr, el) => Array.isArray(el) ? arr.concat(flatten(el)) : arr.concat(el), []);
const count = (arr, item) => flatten(arr).filter(el => el === item).length;
7

Hat erre gondoltam, nagyon

mahoo · 2019. Jan. 4. (P), 21.21
Hat erre gondoltam, nagyon koszi!
Szerintem ezek sokkal szebb megoldasok mint az enyem...
8

A lényeg szempontjából

inf · 2019. Jan. 5. (Szo), 08.36
A lényeg szempontjából tökmindegy. Működik és érthető ránézésre, nagyjából ennyi számít.
9

Persze, tudom, egyszeruen

mahoo · 2019. Jan. 5. (Szo), 09.28
Persze, tudom, egyszeruen csak kivancsi voltam tovabbi megoldasokra.
Teszem hozza, hogy a 3. az, amit leginkabb hasznalnek, az elso ketto sokkal idoigenyesebb (is), de latni szerettem volna, hogyan lehet meg megcsinalni.
10

Ott egy if-else szerencsésebb

inf · 2019. Jan. 5. (Szo), 10.59
Ott egy if-else szerencsésebb lenne, mert feleslegesen bejárja a keresett elemet is, ha tömböt keresel a tömbben. Egyébként ha nincs biztosítva, hogy hierarchiáról van szó, akkor kellene valami circular graph protection bele, mert különben simán végtelen ciklusba mehet. Ez nagyjából annyi, hogy csinálsz egy Set-et, hogy milyen tömbök voltak már a bejárás során, aztán ha valamelyikkel újra találkozol, akkor kivételt dobsz.
15

For

Hidvégi Gábor · 2019. Jan. 7. (H), 18.38
Ami nem tetszik:
- van benne egy 'for'
Mi a baj a for-ral?
16

Semmi. Nekem van olyan

mahoo · 2019. Jan. 7. (H), 20.51
Semmi. Nekem van olyan informacio ragadasom, hogy rekurzioban nem iteralunk. De ugy nez ki tevesen...
18

Úgy látszik másnak is volt

mahoo · 2019. Jan. 7. (H), 22.00
Úgy látszik másnak is volt ilyen beidegződése :). Köszi!