【问题标题】:Sum values of same key that have same user id also retain there date as key具有相同用户 ID 的相同键的总和值也将日期保留为键
【发布时间】:2018-12-06 06:26:34
【问题描述】:

我正在尝试将每个 user_idtotalPlayed 值相加。我不想改变数组的整体结构,我只想通过对totalPlayed 值求和来压缩events 子数组。

这是一个 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;
}

【问题讨论】:

  • 我没有看到键控为 time_played 的元素。
  • 你好安德鲁。键是totalPlayed。很抱歉。
  • 你的函数的输入是什么,它是你提供的第一个sn-p代码吗?
  • 是的,先生。就这样。
  • 你能在这里输出那个 Json 吗?该页面无法在手机上使用。

标签: php multidimensional-array merge sum


【解决方案1】:

您可以使用array_column 查找用户ID,使用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

这只会循环唯一的用户 ID 而不是整个数组。

将来您可以将数组发布为 Json 或 var_export,我们可以更轻松地为您提供帮助。

【讨论】:

  • 你好安德烈亚斯。谢谢你的建议。我用我的代码创建了一个小提琴。链接在这里。 jsfiddle.net/645e2jh1。请看一下,以便您了解我的数组的实际结构。感谢伙伴的帮助。
  • 嗨@Andreas。你检查过我提供的小提琴吗?我认为我们还需要一个外部循环来访问events 键。我收到Undefined index: events 错误。
  • 我做到了,但是当我写信给您时,我无法使用该页面。在移动设备上无法使用该页面
【解决方案2】:

在深层子阵列上使用临时键可以提高性能,而不是迭代 in_array() 调用。更多解释请参见内联 cmets。

代码:(Demo)

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

【讨论】:

  • 给我几分钟解释一下。我的手机速度很慢。
  • 你是对的兄弟。我相信您的代码比其他代码快得多。谢谢你的朋友。
  • 对此我感到非常抱歉。我在想你不在我身边。所以我选择了那个
  • 是的,很抱歉,我在没有电脑的情况下发帖要慢得多。
【解决方案3】:

假设您的主数组名为$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']);

编辑:
由于您有一个 JSON 字符串,因此我得到了与之前相同的结果(假设您的 JSON 字符串称为 $json):

$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) . '</pre>';

文档:

【讨论】:

  • 嗨 AymDev,我收到 Undefined index: user_id 错误。您能否编辑您的解决方案。
  • in_array() 很慢。找到更好的方法。
  • @Neeraj 我测试了它并且它工作正常,你是否将$data['events'] 发送给函数而不仅仅是$data
  • 嗨@mickmackusa 我不知道。您是否有关于此问题的良好链接或只是“找到更好的方法”。 ?无论如何,另一个答案看起来好多了。
  • 如果 OP 提供了一个现成的变量,我将提供一个教育性的答案。此类问题大约每 48 小时被问一次。这个可能不同,但绝对与其他许多相同。
猜你喜欢
  • 2019-07-09
  • 2021-04-10
  • 1970-01-01
  • 2017-04-07
  • 2014-03-12
  • 1970-01-01
  • 2019-08-18
  • 2018-10-26
  • 2019-05-07
相关资源
最近更新 更多