сокращение массива в другой массив - PullRequest
2 голосов
/ 05 марта 2020

Внутри laravel шаблона блэйда я пытаюсь уменьшить массив следующим образом:

$longList = [['box' => 1, 'kg' => 2], ['box' => 2, 'kg' => 2], ['box' => 3, 'kg' => 3]];

примерно так: $reducedList = [['count' => 2, 'kg' => 2], ['count' => 1, 'kg' => 3]];

Это то, что я до сих пор:

@php
          $variableWeights = isset($sale->variable_weight_json) ? collect(json_decode($sale->variable_weight_json, true)) : null;
          $groups = array();

          if (isset($variableWeights)) {
            $groups = $variableWeights->reduce(function($carry, $item) {
              $index = array_search($item['kg'], array_column($carry, 'weight'));
              if (isset($index)) {
                $existing = $carry[$index];
                array_splice($carry, $index, 1, [
                  'count' => $existing['count'] + 1,
                  'weight' => $item['kg']
                ]);
              } else {
                array_push($carry, [
                  'count' => 1,
                  'weight' => $item['kg'],
                ]);
              }
              return $carry;
            }, array());
          }
        @endphp

Но это дает мне ошибку Неопределенное смещение: 0

Я новичок в php. Как исправить код или есть лучший подход для достижения желаемого результата?

Ответы [ 5 ]

2 голосов
/ 05 марта 2020

Почему бы вам не сократить его до чего-то более простого, подобного этому

$reducedList = [2 => 2, 3 => 1]

, где вес - это индекс, а значение - это число.

$reducedList = [];
foreach ($longList as $box) {
    if (isset($reducedList[$box['kg']]) {
        $reducedList[$box['kg']]++;
    } else {
        $reducedList[$box['kg']] = 1;
    }
}

Таким образом, вы избегаете сложности, но все равно получаете тот же объем информации.

1 голос
/ 05 марта 2020

Вы можете использовать сексуальный метод countBy() (в сочетании со знаменитым map() one) класса Collection .

Попробуйте это:

$longList = [['box' => 1, 'kg' => 2], ['box' => 2, 'kg' => 2], ['box' => 3, 'kg' => 3]];

$shortList = collect($longList)
    ->countBy('kg')
    ->map(function ($count, $kg) {
        return [
            'kg' => $kg, 
            'count' => $count,
        ];
    });

С этим вы получите:

dd($shortList);
=> Illuminate\Support\Collection {#3380
     all: [
       2 => [
         "kg" => 2,
         "count" => 2,
       ],
       3 => [
         "kg" => 3,
         "count" => 1,
       ],
     ],
   }

Здесь у вас есть рабочая демонстрация .

1 голос
/ 05 марта 2020

Полагаю, вы можете добиться этого с помощью кода, подобного следующему:

$longList = [['box' => 1, 'kg' => 2], ['box' => 2, 'kg' => 2], ['box' => 3, 'kg' => 3]];

$reducedList = array_values(array_reduce(
    $longList,
    function($carry, $item) {
        if (isset($carry[$item['kg']])) {
            ++$carry[$item['kg']]['count'];
        } else {
            $carry[$item['kg']] = ['count' => 1, 'kg' => $item['kg']];
        }

        return $carry;
    },
    []
));

print_r($reducedList);

Вот рабочий пример .

1 голос
/ 05 марта 2020

не используйте функцию isset(). он проверяет только переменную, существующую. используйте empty() или другое условие, оно проверит существующую переменную и значение. попробуй это.

@php
          $variableWeights = isset($sale->variable_weight_json) ? collect(json_decode($sale->variable_weight_json, true)) : null;
          $groups = array();

          if ($variableWeights->isNotEmpty()) {
            $groups = $variableWeights->reduce(function($carry, $item) {
              $index = array_search($item['kg'], array_column($carry, 'weight'));
              if ($index != false ) {
                $existing = $carry[$index]?: false;
                if ($existing) {
                   array_splice($carry, $index, 1, [
                     'count' => $existing['count'] + 1,
                     'weight' => $item['kg']
                   ]);
                }
              } else {
                array_push($carry, [
                  'count' => 1,
                  'weight' => $item['kg'],
                ]);
              }
              return $carry;
            }, array());
          }
        @endphp
0 голосов
/ 05 марта 2020

isset проверяет, установлена ​​ли переменная (то есть существует ли она, а не NULL). Поскольку я (и основные разработчики) с трудом представляю, в каких случаях array_search может вернуть NULL, есть руководство , в котором говорится:

Возвращает ключ для иглы, если он находится в массиве, FALSE в противном случае.

Итак, вам нужно проверить, не $index не false:

$index = array_search($item['kg'], array_column($carry, 'weight'));
// Note that I use `!==` because using `!=` will convert 
// `0` index to false, which is not correct in your case
if (false !== $index) {
...