【问题标题】:Array data smart merging with Php数组数据与php智能合并
【发布时间】:2014-06-25 03:18:42
【问题描述】:

基本上我得到了一个具有这种结构的数组:

数组:

0 => {
    time: "090019"
    val: "2.444"
    qta: "292"
    dir: "up"
    param: "S"
}

1=>  {
    time: "090019"
    val: "2.442"
    qta: "938"
    dir: "dwn"
    param: "N"
}

2 =>  {
    time: "090019"
    val: "2.442"
    qta: "220"
    dir: "up"
    param: "N"
}

3 =>  {
    time: "100043"
    val: "2.44"
    qta: "220"
    dir: "dwn"
    param: "N"
}

.. 以此类推

n =>  {
    time: "103051"
    val: "2.444"
    qta: "330"
    dir: "dwn"
    param: "N"
}

我的目标是获得一个结构相同的数组,其中数据将以精确的方式合并。

如果两个或多个数组值具有相同的时间 (time) 和值 (val),它们将是:如果它们具有相同的方向 (dir),则相加,否则相减(在这种情况下,结果方向将是较高值的(dir))。参数(param)无关紧要。

我对 Php 很陌生,当我必须解决这样的问题时,我不知道如何处理。

希望足够清楚,任何建议将不胜感激。

编辑:

生成的数组将如下所示:

0 => {
    time: "090019"
    val: "2.444"
    qta: "292"
    dir: "up"
    param: "S"
}

1 =>  {
    time: "090019"
    val: "2.442"
    qta: "718"
    dir: "dwn"
    param: "N"
}

2 =>  {
    time: "100043"
    val: "2.44"
    qta: "220"
    dir: "dwn"
    param: "N"
}


..

n =>  {
    time: "103051"
    val: "2.444"
    qta: "330"
    dir: "dwn"
    param: "N"
}

【问题讨论】:

  • 你能举个例子,在你的初始数组中有五个项目,然后你希望结果看起来像什么?
  • 如果你有三四个相同的项目怎么办?你想如何合并它们?
  • 如果你有四个具有相同时间和 val 的项目,你说你想让它们“如果它们有相同的方向 (dir),则添加,如果它们没有,则减去”但是你怎么做当您有四个方向值时确定“相同方向”?您的意思是所有“向上”目录都添加到“向下”吗?那么从哪个中减去哪个?你的意思是上升是积极的,下降是消极的,你把它们加在一起吗?
  • 没错!我的意思是向上是正数,向下是负数,并将它们加在一起,但最后数字将没有符号,如果是正数,它将是“向上”,如果是负数,它将是“向下”。我的经验告诉我,通常最多连续 3 个可能具有相同的时间/验证。
  • 这可能是包含在问题中的好信息:)

标签: php arrays sorting foreach merge


【解决方案1】:

这是一个有趣的问题,所以这可能对你有用,开箱即用 :)

首先,定义你的项目:

$items = array(

    array(
        "time" => "090019",
        "val" => "2.444",
        "qta" => "292",
        "dir" => "up",
        "param" => "S",
    ),

    array(
        "time" => "090019",
        "val" => "2.442",
        "qta" => "938",
        "dir" => "dwn",
        "param" => "N",
    ),

    array(
        "time" => "090019",
        "val" => "2.442",
        "qta" => "220",
        "dir" => "up",
        "param" => "N",
    ),

    array(
        "time" => "100043",
        "val" => "2.44",
        "qta" => "220",
        "dir" => "dwn",
        "param" => "N",
    ),

);

接下来,遍历 items 数组一次,根据相同的时间和 val 将项目分组:

$grouped_items = array();

foreach($items as $item) {
    $key = "{$item['time']}-{$item['val']}";

    if( empty($grouped_items[$key]) ) $group_items[$key] = array();

    $grouped_items[$key][] = $item;
}

此时,您有一个键等于 time-val 的数组。其中每一个都是一个子数组,其中包含与该 item-val 匹配的所有项目的列表(因此您将相同的 time/val 项目组合在一起)。最后,您可以创建合并列表:

$final_items = array();

foreach($grouped_items as $item_list) {
    $final_items[] = mergeItems($item_list);
}

// merge a list of items with the same time and val
function mergeItems($items) {
    $merged_item = array(
        "time" => $items[0]['time'],
        "val" => $items[0]['val'],
        "qta" => 0,
        "dir" => null,
        "param" => $items[0]['param'],
    );

    // add or subtract qta values
    foreach($items as $item) {
        if( $item['dir'] == "up" ) {
            $merged_item["qta"] += (int) $item["qta"];
        }
        else {
            $merged_item["qta"] -= (int) $item["qta"];
        }
    }

    // set the final qta and dir value
    if( $merged_item["qta"] < 0 ) {
        $merged_item["qta"] *= -1;
        $merged_item["dir"] = "down";
    }
    else {
        $merged_item["dir"] = "up";
    }

    return $merged_item;
}

现在 $final_items 有你的合并列表。

如果您将所有这些粘贴到一个 PHP 脚本中,它将运行并为您提供所需的输出。如果它不能完全按照您的实际数据进行操作,那么您忘记在问题中提及某些内容,并且可能可以使用此示例来创建可以工作的内容:)

【讨论】:

  • 首先感谢您为此付出的时间。现在,我的目的是学习如何处理这种情况。你能解释一下第一个 foreach 循环是如何工作的吗?我不清楚..
  • @Plastic 您想找出列表中的哪些项目匹配,以便您可以合并它们。第一个 foreach 基于匹配时间和 val 遍历项目并将它们组合在一起。它将匹配的项目组合成小的“子数组”。
  • 这是创建小“子数组”的命令吗? $key = "{$item['time']}-{$item['val']}"; $group_items[$key] = array(); $grouped_items[$key][] = $item;第一行是什么意思?
  • 我正在创建一个对于该时间/验证组合而言是唯一的密钥。基本上,任何具有相同 time/val 的项目都会以相同的键结束。然后我检查它是否已经被创建(例如,如果 foreach 循环的前一次迭代已经创建了它)。如果没有,我会将数组中的那个键设置为一个空数组。然后我追加到它(如果它是一个新数组,它将只有一个项目,如果它是在前一次迭代中创建的,它将有一个项目)。
【解决方案2】:

这是一个通用答案,您可以使用新的 qta 做您想做的事情:

$items = array([put your data here]);

for($i=0; $i < count($items); $i++) {
    for($j=0; $j < count($items); $j++) {
        // don't compare and item to itself
        if($i == $j) continue;

        // if their times and values are equal
        if( $items[$i]["time"] == $items[$j]["time"] && $items[$i]["val"] == $items[$j]["val"]) {
            // dirs are the same
            if( $items[$i]["dir"] == $items[$j]["dir"] ) {
                $newqta = $items[$i]["qta"] + $items[$j]["qta"];
                $newdir = $items[$i]["dir"];
            }
            // dirs are different
            else {
                $newqta = $items[$i]["qta"] - $items[$j]["qta"];

                if( $items[$i]["qta"] > $items[$j]["qta"] ) {
                    $newdir = $items[$i]["dir"];
                }
                else {
                    $newdir = $items[$j]["dir"];
                }
            }

            // do something with $newqta and $newdir
        }
    }
}

【讨论】:

  • 感谢您的快速答复。如果将添加/减去两个或多个项目,那么结果项目的 'dir' 参数的值是多少?
  • 加/减是什么意思?你想添加什么?还是您的意思是包含/不包含在最终数据数组中?
  • 假设项目 2 和 3 是: 1=> { time: "090019" val: "2.44" qta: "938" dir: "dwn" param: "N" } 2 => { time: "090019" val: "2.44" qta: "220" dir: "up" param: "N" } qta 将是 938 - 220 = 718 的结果,但数组中的新项目将具有 dir='向上”还是“向下”?我希望那将是“下降”,因为 938 更大..
  • @Plastic 用一个例子来澄清你原来的问题。
  • 我的目标是获得一个具有相同结构和合并数据的新数组
猜你喜欢
  • 2017-09-02
  • 2018-07-07
  • 1970-01-01
  • 1970-01-01
  • 2011-02-12
  • 2015-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多