Суммарные значения одного и того же ключа с одинаковым идентификатором пользователя также сохраняют дату в качестве ключа - PullRequest
0 голосов
/ 27 июня 2018

Я пытаюсь сложить значения totalPlayed для каждого user_id. Я не хочу изменять общую структуру массива, я просто хочу сжать подмассивы events путем суммирования значений totalPlayed.

Вот пример массива как json:

[
  {
    "date": "May 29",
    "date_start": "2018-05-29 05:00:00",
    "date_end": "2018-05-30 04:59:59",
    "interval": 29,
    "calDay": "29 days ago",
    "events": [
      {
        "totalPlayed": 184,
        "user_id": 479
      },
      {
        "totalPlayed": 906,
        "user_id": 479
      },
      {
        "totalPlayed": 400,
        "user_id": 1446
      },
      {
        "totalPlayed": 500,
        "user_id": 1446
      }

    ]
  },
  {
    "date": "May 30",
    "date_start": "2018-05-30 05:00:00",
    "date_end": "2018-05-31 04:59:59",
    "interval": 28,
    "calDay": "28 days ago",
    "events": [
      {
        "totalPlayed": 1469,
        "user_id": 1626
      },
      {
        "totalPlayed": 1482,
        "user_id": 1690
      },
      {
        "totalPlayed": 1434,
        "user_id": 1690
      }
    ]
  }
]

Хотелось бы получить такой результат:

array (
  0 => 
  array (
    'date' => 'May 29',
    'date_start' => '2018-05-29 05:00:00',
    'date_end' => '2018-05-30 04:59:59',
    'interval' => 29,
    'calDay' => '29 days ago',
    'events' => 
    array (
      0 => 
      array (
        'totalPlayed' => 1090,
        'user_id' => 479,
      ),
      1 => 
      array (
        'totalPlayed' => 900,
        'user_id' => 1446,
      ),
    ),
  ),
  1 => 
  array (
    'date' => 'May 30',
    'date_start' => '2018-05-30 05:00:00',
    'date_end' => '2018-05-31 04:59:59',
    'interval' => 28,
    'calDay' => '28 days ago',
    'events' => 
    array (
      0 => 
      array (
        'totalPlayed' => 1469,
        'user_id' => 1626,
      ),
      1 => 
      array (
        'totalPlayed' => 2916,
        'user_id' => 1690,
      ),
    ),
  ),
)

Я попробовал следующую функцию, но она не работает для меня.

function computeOutcome($array) {
    $result=array();
    foreach ($array as $item) {
        $id=$item['user_id'];
        if (isset($result[$id])) {
            $result[$id]=$result[$id]+$item['time_played'];
        } else {
            $result[$id]=$item['time_played'];
        }
    }
    return $result;
}

Ответы [ 3 ]

0 голосов
/ 27 июня 2018

Вы можете использовать array_column для поиска идентификатора пользователя, array_intersect для поиска соответствующих значений и array_sum для суммирования значений.

$data =json_decode('
[
{
"date": "May 29",
"date_start": "2018-05-29 05:00:00",
"date_end": "2018-05-30 04:59:59",
"interval": 29,
"calDay": "29 days ago",
"events": [
  {
    "totalPlayed": 184,
    "user_id": 479
  },
  {
    "totalPlayed": 906,
    "user_id": 479
  },
  {
    "totalPlayed": 400,
    "user_id": 1446
  },
  {
    "totalPlayed": 500,
    "user_id": 1446
  }

 ]
},
{
"date": "May 30",
"date_start": "2018-05-30 05:00:00",
"date_end": "2018-05-31 04:59:59",
"interval": 28,
"calDay": "28 days ago",
"events": [
  {
    "totalPlayed": 1469,
    "user_id": 1626
  },
  {
    "totalPlayed": 1482,
    "user_id": 1690
  },
  {
    "totalPlayed": 1434,
    "user_id": 1690
  }
]
}
]', true);
Foreach($data as $key => $arr){
    $userid = array_column($arr["events"], "user_id");
    $played = array_column($arr["events"], "totalPlayed");
    Foreach(array_unique($userid) as $id){
        $temp = array_intersect_key($played, array_intersect($userid, [$id]));
        $new[$key]['events']['date'] = $arr['date'];
        $new[$key]['events'][] = ['total played' => array_sum($temp), 'user_id' => $id];
    }
}
Var_dump($new);

https://3v4l.org/G1jKI

Это зациклит только уникальные идентификаторы пользователей вместо полного массива.

В будущем вы можете публиковать массивы как Json или как var_export, и нам будет намного легче помочь вам.

0 голосов
/ 27 июня 2018

Использование временных ключей в ваших глубоких подмассивах повышает производительность по сравнению с повторными вызовами in_array(). См. Встроенные комментарии для дополнительных объяснений.

Код: ( Демо )

function computeOutcome($array) {
    foreach ($array as &$set) {  // modify by reference
        $tmp = [];  // use a fresh temporary array for each date-set
        foreach ($set['events'] as $record) {
            $id = $record['user_id'];
            if (isset($tmp[$id])) {
                $tmp[$id]['totalPlayed'] += $record['totalPlayed'];  // increase the tally
            } else {
                $tmp[$id] = $record;  // store the whole row
            }
        }
        $set['events'] = array_values($tmp);  // remove temporary keys
    }
    return $array;
}

$json = <<<JSON
[
  {
    "date": "May 29",
    "date_start": "2018-05-29 05:00:00",
    "date_end": "2018-05-30 04:59:59",
    "interval": 29,
    "calDay": "29 days ago",
    "events": [
      {
        "totalPlayed": 184,
        "user_id": 479
      },
      {
        "totalPlayed": 906,
        "user_id": 479
      },
      {
        "totalPlayed": 400,
        "user_id": 1446
      },
      {
        "totalPlayed": 500,
        "user_id": 1446
      }

    ]
  },
  {
    "date": "May 30",
    "date_start": "2018-05-30 05:00:00",
    "date_end": "2018-05-31 04:59:59",
    "interval": 28,
    "calDay": "28 days ago",
    "events": [
      {
        "totalPlayed": 1469,
        "user_id": 1626
      },
      {
        "totalPlayed": 1482,
        "user_id": 1690
      },
      {
        "totalPlayed": 1434,
        "user_id": 1690
      }
    ]
  }
]
JSON;

var_export(computeOutcome(json_decode($json, true)));
0 голосов
/ 27 июня 2018

Если ваш основной массив называется $data, это решение создает новый массив с суммированными значениями, затем вы можете заменить исходный массив новым созданным:

function computeOutcome($array) {
    $events = [];
    foreach ($array as $evt) {
        if (in_array($evt['user_id'], array_column($events, 'user_id'))) {
            $key = array_search($evt['user_id'], array_column($events, 'user_id'));
            $events[$key]['totalPlayed'] += $evt['totalPlayed'];
        } else {
            $events[] = $evt;
        }
    }
    return $events;
}

$data['events'] = computeOutcome($data['events']);

EDIT:
Поскольку у вас есть строка JSON , я получил тот же результат, что и до этого (при условии, что ваша строка JSON называется $json):

<code>$data = json_decode($json, true);

// Still using the function I wrote before
for ($i = 0; $i < count($data); $i++) {
    $data[$i]['events'] = computeOutcome($data[$i]['events']);
}

// Print result
echo '<pre>' . print_r($data, true) . '
';

Документация:

...