【问题标题】:Get deltas from an array using foreach in PHP在 PHP 中使用 foreach 从数组中获取增量
【发布时间】:2020-05-31 09:57:44
【问题描述】:

我正在尝试使用 json api 显示一些值。它以数字形式返回日期和一些密度值。成功地,我打印了来自 url 的所有返回值。现在,我想找出一个密度值与前一天密度值之间的差异。

我知道如何计算正常静态数字的差异。但是,我不确定如何在 foreach 循环中实现这一点。

PHP 代码:

$json_url = "https://www.example.com/api";

$json = file_get_contents($json_url);
$obj  = json_decode($json,true);
$data = $obj["data"];

foreach(array_slice($data, 0, 10) as $k) {

    echo $k["date"]." - ".$k["density"]."<br/><br/>";

}

电流输出:

14-02-2020 - 110 13-02-2020 - 114 12-02-2020 - 112 11-02-2020 - 110 10-02-2020 - 105 2020 年 7 月 2 日 - 125 06-02-2020 - 122 05-02-2020 - 118 04-02-2020 - 119 03-02-2020 - 119

预期输出:

2020 年 2 月 14 日 - 110 - 与上一个日期的差异为 -4 2020 年 2 月 13 日 - 114 - 与上一个日期的差异为 +2 2020 年 2 月 12 日 - 112 - 与上一个日期的差异为 +2 2020 年 11 月 2 日 - 110 - 与上一个日期的差异为 +5 2020 年 2 月 10 日 - 105 - 与上一个日期的差异为 -20 2020 年 7 月 2 日 - 125 - 与上一日期的差异为 +3 2020 年 6 月 2 日 - 122 - 与上一个日期的差异为 +4 2020 年 5 月 2 日 - 118 - 与上一个日期的差异为 -1 04-02-2020 - 119 - 没有区别 - 相同 03-02-2020 - 119 - 没有区别 - 相同

【问题讨论】:

  • 请也发布 JSON 字符串
  • 最后一行 +1 对我来说没有逻辑意义。请解释一下。
  • @mickmackusa 是的,你是对的。那是我的错误。我会这样显示03-02-2020 - 119
  • 没有差异文本?请编辑您的问题。

标签: php arrays json foreach


【解决方案1】:

要达到预期的效果,您需要一次迭代数组两个元素。使用foreach 完全不能轻易做到这一点。因此,我将实现一个生成器,它一次从数组中返回成对的值。

function getPairs(Array $array) {
    reset($array);
    do {
        $a1  = current($array);
        $key = key($array);
        $a2  = next($array);
        yield [$a1, $a2];
    } while($key = key($array) !== null);
}

然后你可以使用这个生成器实现来遍历数组,达到预期的效果。

$array = [
    ["date" => "14-02-2020", "density" => 110],
    ["date" => "13-02-2020", "density" => 114],
    ["date" => "12-02-2020", "density" => 112],
    ["date" => "11-02-2020", "density" => 110],
    ["date" => "10-02-2020", "density" => 105],
    ["date" => "07-02-2020", "density" => 125],
    ["date" => "12-02-2020", "density" => 112],
    ["date" => "06-02-2020", "density" => 122],
    ["date" => "05-02-2020", "density" => 118],
    ["date" => "04-02-2020", "density" => 119],
    ["date" => "03-02-2020", "density" => 119],
];

foreach(getPairs($array) as [$a, $b]) {
    // We must check if $b is empty to account for end of the array
    if ($b) {
        $diff = $a["density"] - $b["density"];
    } else { // Otherwise there are no more elements to diff against
        $diff = 0;
    }
    if ($diff > 0) {
        $diff = "+$diff";
    }
    echo "{$a['date']} - {$a['density']} - Diff is $diff from Previous Date<br><br>";
}

这应该会给你想要的输出。

2020 年 2 月 14 日 - 110 - 与上一个日期的差异为 -4 2020 年 2 月 13 日 - 114 - 与上一个日期的差异为 +2 2020 年 2 月 12 日 - 112 - 与上一个日期的差异为 +2 2020 年 11 月 2 日 - 110 - 与上一个日期的差异为 +5 2020 年 2 月 10 日 - 105 - 与上一个日期的差异为 -20 2020 年 7 月 2 日 - 125 - 与上一个日期的差异为 +13 2020 年 2 月 2 日 - 112 - 与上一个日期的差异为 -10 2020 年 6 月 2 日 - 122 - 与上一个日期的差异为 +4 2020 年 5 月 2 日 - 118 - 与上一个日期的差异为 -1 04-02-2020 - 119 - 与上一个日期的差异为 0 03-02-2020 - 119 - 与上一个日期的差异为 0

注意

从技术上讲,您实际上并没有在这里得到当前日期和上一个日期之间的差异。相反,您得到的是当前日期和下一个日期之间的差异。如果您获得了先前日期之间的增量,则根本不需要下一个日期的信息。相反,您只需使用一个临时变量来存储最后一个 density 值,并在每次迭代时对其进行比较。不过,我已根据您的预期结果调整了答案。

否则预期的输出实际上是:

2020 年 2 月 14 日 - 110 - 与上一个日期的差异为 +110 2020 年 2 月 13 日 - 114 - 与上一个日期的差异为 +4 2020 年 12 月 2 日 - 112 - 与上一个日期的差异为 -2 2020 年 11 月 2 日 - 110 - 与上一个日期的差异为 -2 2020 年 2 月 10 日 - 105 - 与上一个日期的差异为 -5 2020 年 7 月 2 日 - 125 - 与上一个日期的差异为 +20 2020 年 2 月 2 日 - 112 - 与上一个日期的差异为 -13 2020 年 6 月 2 日 - 122 - 与上一个日期的差异为 +10 2020 年 5 月 2 日 - 118 - 与上一个日期的差异为 -4 2020 年 4 月 2 日 - 119 - 与上一个日期的差异为 +1 03-02-2020 - 119 - 与上一个日期的差异为 0

为了实现这一点,您根本不需要我使用的生成器实现。您可以简单地使用常规的foreach 循环来执行此操作,如下所示:

$lastDiff = 0; // Initialize the diff to 0

foreach($array as $a) {
    $date = $a['date'];
    $density = $a['density'];
    $diff = $a["density"] - $lastDiff; // diff against the last known value
    if ($diff > 0) {
        $diff = "+$diff";
    }
    echo "$date - $density - Diff is $diff from Previous Date<br><br>";
    $lastDiff = $a["density"]; // store the last known density here for the next iteration
}

【讨论】:

  • 谢谢。除了最后一种情况外,它都有效。如果我使用array_slice($commits, 0, 10)..,它在最后一种情况下不起作用
  • 好吧,你必须考虑到这样一个事实,在最后一种情况下,没有什么可以比较的。假设数组是[1,2,2]。第一对是[1,2],第二对是[2,2],最后一对实际上是[2],因为数组中没有任何内容。所以在这种情况下,你必须检查$b 是否真的存在。
  • 我已经更新了我的答案以解决这种极端情况。
【解决方案2】:

只是一个替代的、较短的版本。这仅适用于直接的for() 循环,处理当前和下一个项目。循环在最后一个的第二个处停止,因为最后一个将始终与 下一个...

相同
$end = count($array)-1;
for ( $i = 0; $i < $end; $i++ ) {
    if ( $array[$i]["density"] == $array[$i+1]["density"] )    {
        echo "No Difference - Same".PHP_EOL;
    }
    else    {
        echo "Diff is ".($array[$i]["density"]-$array[$i+1]["density"])." from Previous Date".PHP_EOL;
    }

}
echo "No Difference - Same".PHP_EOL;

【讨论】:

  • 查看 OP 的评论,关于不在最终迭代中添加文本。
【解决方案3】:

我会在一个循环中执行此操作并使用printf() 函数来格式化签名值。

我写 \n\n 代替你的 &lt;br&gt;&lt;br&gt; 以便我的演示正确呈现。

我发现这个 sn-p 易于阅读和管理。

代码:(Demo)

$prev = null;
foreach ($data as $row) {
    if ($prev !== null) {
        $diff = $prev - $row['density'];
        if (!$diff) {
            echo " - No Difference - Same\n\n";
        } else {
            printf(" - Diff is %+d from Next Date\n\n", $diff);
        }
    }
    echo "{$row['date']} - {$row['density']}";
    $prev = $row['density'];
}

输出:

14-02-2020 - 110 - Diff is -4 from Next Date

13-02-2020 - 114 - Diff is +2 from Next Date

12-02-2020 - 112 - Diff is +2 from Next Date

11-02-2020 - 110 - Diff is +5 from Next Date

10-02-2020 - 105 - Diff is -20 from Next Date

07-02-2020 - 125 - Diff is +3 from Next Date

06-02-2020 - 122 - Diff is +4 from Next Date

05-02-2020 - 118 - Diff is -1 from Next Date

04-02-2020 - 119 - No Difference - Same

03-02-2020 - 119

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-11
    • 2016-02-14
    • 1970-01-01
    • 2012-07-11
    • 2012-06-15
    • 2015-11-27
    • 2012-12-18
    相关资源
    最近更新 更多