Zliczenie elementów rekursywnie

Zliczenie elementów rekursywnie
Chudy20007
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0

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

Kopiuj
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

Patryk27
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
  • Postów: 13042
2

Może tak?

Kopiuj
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;
}
Chudy20007
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
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:

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

Patryk27
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
  • Postów: 13042
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ę.

Chudy20007
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
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.

Patryk27
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
  • Postów: 13042
1

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

Chudy20007
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0

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

Kopiuj
[
      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.

.__.
  • Rejestracja: dni
  • Ostatnio: dni
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(?)

Chudy20007
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
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.

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

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.