Zliczenie elementów rekursywnie

0

Witam. Otóż posiadam pewną drzewiastą strukturę, która posiada zagnieżdżone elementy:

array:4 [
  1 => array:3 [
    3 => array:2 [
      4 => array:2 [
        12 => array:1 [
          "val" => 1
        ]
        "val" => 3
      ]
      "val" => 1
    ]
    11 => array:1 [
      "val" => 1
    ]
    "val" => 3
  ]
  2 => array:2 [
    6 => array:3 [
      8 => array:2 [
        9 => array:1 [
          "val" => 1
        ]
        "val" => 2
      ]
      10 => array:1 [
        "val" => 1
      ]
      "val" => 1
    ]
    "val" => 2
  ]
  5 => array:1 [
    "val" => 1
  ]
  7 => array:1 [
    "val" => 2
  ]
]

Dla każdego indeksu z tych tablic chciałbym zliczyć pola "val".
Przykładowo dla indeksu 1 funkcja powinna zliczyć 9 elementów, dla 3 - 5 itd.
Mógłby mnie ktoś nakierować jak poprawnie pozliczać te elementy za pomocą rekursji? Jeżeli wątek jest w nieodpowiednim dziale to proszę o przeniesienie wątku.

Pozdrawiam

2

Może tak?

function sum(array $items): int {
  $sum = 0;
 
  foreach ($items as $item) {
  	if (is_array($item)) {
  		$sum += sum($item);
  	} else if (is_int($item)) {
  		$sum += $item;
  	}
  }
 
  return $sum;
}
0

Hej Patryk. Zauważ, że każdy element ma klucz "val". Chciałbym dla każdego elementu zsumować te wartości (wliczając w to również wartości, które znajdują się w dzieciach).

Aktualnie stanąłem na :
Edit:

  private function foo($arr, $c) {
    foreach ($arr as $key => $element) {
      if (!isset($c[$key]) && $key !== "val") {
        $c[$key] = 0;
      }
      if ($key !== "val") {
        $c[$key] += $element["val"];
      }
      if (is_array($element)) {
        $c =  $this->foo($element, $c);
      }
    }

    return $c;
  }

Zliczane są wartości samych rodziców, nie uwzględnia wartości dzieci.

0

Mógłbyś przygotować jakiś zbiór danych wejściowych oraz oczekiwanych wartości?
Najwygodniej w formie testu PHPUnit, ale w zasadzie cokolwiek da radę.

0

Podsyłam paczkę, która zawiera test jednostkowy oraz dwa pliki dto, które odzwierciedlają strukturę.
Jedna z metod zwraca wyżej wymienioną tablicę. Tablica ta miała posłużyć do zsumowania elementów i zwrócenia.

Dane wejściowe to tablice, które zawierają obiekty w postaci tych dwóch dtosów.
Dane wyjściowe : tablica w postaci** id danej kategorii** => liczba dokumentów.

http://wrzucplik.pl/pokaz/1941190---c73d.html

Edit - przykład dlaczego element 3 powinien mieć wartość 5:
Element 3 posiada wartość 1, jego dziecko o numerze 4 ma wartość 3 oraz ostatnie dziecko o numerze 12 ma wartość 1. Razem daje wartość 5.
Jest to swego rodzaju struktura drzewiasta.

1

W takim razie mój kod działa prawidłowo: https://ideone.com/GmA2Na.

0

No dobrze, ale jak mogę zliczyć te elementy dla każdego indeksu za jednym zamachem, aby otrzymać spłaszczoną tablicę w stylu:

[
      1 => 9,
      2 => 7,
      3 => 5,
      4 => 4,
      8 => 2,
      9 => 2
]

Generalnie mam problem z otrzymaniem wyników dla zagnieżdżonych dzieci.
Rozumiem, że muszę metodę sum wywołać za pomocą kolejnej rekurencji? Dodatkowo dane wejściowe mogą być różne, przez co nie mogę "ręcznie" wywoływać tej metody dla każdego z elementów.

0

Przecież funkcja Patryka zwraca sumę wszystkich zagnieżdżonych wartości dla konkretnego klucza. Jakim problemem jest puścić pętle na każdy root element i zrobić choćby echo $key.' => '.sum($array[$key])? Chyba, że nie zrozumiałem pytania(?)

1

No dobrze, ale jak powinienem zaimplementować pętlę rekurencyjnie, aby dla wszystkich kluczy (nawet tych zagnieżdżonych) zwróciło mi te wartości (również dla 3, 6 itd.)?

Podkreślam, że jest to struktura drzewiasta.

Edit:
Patryk bardzo dziękuję za pomoc. Bardzo mi to pomogło.
Również dziękuję .__. za odpowiedź.

Przesyłam moją dopisaną metodę, która rozwiązuje zadany problem.

  private function bar($b, $p = []) {
    foreach ($b as $key => $x) {
      if (is_array($x)) {
          $p[$key] = $this->foo($x);
          $p = $this->bar($x, $p);
      } 
    }

    return $p;
  }

W wyniku tej metody otrzymuję wartości dla każdego indeksu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1