2

在 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

但它给了我错误 Undefined offset: 0

我是 php 新手。应该如何更正代码或者是否有更好的方法来达到预期的结果?

4

5 回答 5

2

你为什么不把它简化为像这样更简单的东西

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

其中权重是索引,值是计数。

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

这样可以避免复杂性,但您仍然可以获得相同数量的信息。

于 2020-03-05T15:42:27.520 回答
1

不要使用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
于 2020-03-05T15:35:09.410 回答
1

我想您可以使用以下代码来实现它:

$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);

这是一个工作示例

于 2020-03-05T15:44:28.917 回答
1

你可以使用Collection类的sexycountBy()方法(结合著名的方法map()) 。

试试这个:

$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,
       ],
     ],
   }

在这里你有一个工作演示

于 2020-03-05T15:49:04.723 回答
0

isset检查是否设置了变量(即它存在而不是 NULL)。由于我(和核心开发人员)很难想象在哪些情况下array_search可以返回NULL,所以有一本手册说:

如果在数组中找到 needle 的键,则返回它,否则返回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) {
于 2020-03-05T15:44:32.827 回答