将带有std :: accumulate的C ++映射移植到PHP

时间:2011-09-03 14:25:33

标签: php c++ map porting

我对PHP中的数组操作并不十分精通,所以我有一个简单的移植问题。在C ++中,我有一个映射std::map<int, int>,对于该键,隐式排序是结构的关键部分。我想要做的是总结一系列初始键的所有值,我喜欢这样:

// accumulate helper, since "value_type" is "pair<int, int>"
int pair_adder(int n, const std::map<int, int>::value_type & p) { return n + p.second; }

// To add up values for keys up to N:
int total_value_up_to_time_N(int N)
{
  return std::accumulate(mymap.begin(), mymap.upper_bound(N), 0, pair_adder);
}

在PHP中编写这个数据结构和累加器的惯用方法是什么?

解释上下文:数据结构是一个简单的时间序列,我想知道我在N时累积了多少。 C ++ map总是按键排序,因此我可以按任意顺序添加元素mymap[time] = value;,并且地图始终按时间顺序包含元素。

解释积累:accumulate函数汇总其键不大于N的所有地图值。例如,拍摄此地图:

 mymap = { { 1, 20}, {2, 30}, {3, -10}, {4, 15} };

然后对于N = 2我积累50,对于N = 3我积累40,而对于N = 12我累积55。


更新:我刚才意识到实际上没有理由为什么每个时间戳只出现一次,所以数据结构应该是std::multimap<int, int>。相同的累积函数逐字工作,但如果PHP解决方案需要时间作为数组键,那么它将不再起作用。但这并不严格;我认为每次都需要独特的解决方案就足够了。

3 个答案:

答案 0 :(得分:5)

我对C ++并不是很熟悉,但我会尝试用PHP快速概述数组,然后回答你关于求和的问题。

PHP中的每个数组都可以被视为有序映射。与C ++不同,对类型没有限制,数组只是从键到值的映射。

要创建阵列,您可以使用以下内容:

$arr = array();

要向数组添加项目,有两种方法可以执行此操作。首先,您可以使用[]运算符将新元素添加到数组的末尾。此元素的键将是(最高int键+ 1),第一个键从零开始。例如:

$arr[] = 1;
$arr[] = 2;
$arr[] = 4;

此时,$arr现在是一个包含以下键/值的地图:

0 => 1
1 => 2
2 => 4

我们还可以添加特定的键和值:

$arr[42] = 'cool';
$arr['foo'] = 'bar';

此时地图将如下所示:

0 => 1
1 => 2
2 => 4
42 => 'cool'
'foo' => 'bar'

PHP内置了quite a few functions来处理数组。例如,有一些函数用于排序数组(按键和值,以用户定义的方式),组合数组,搜索数组,将函数应用于所有元素,减少数组等。此外,PHP构造foreach可用于迭代数组。使用方法如下:

foreach ($arr as $key => $value) {
    echo 'Value of key ' . $key . ' is ' . $value;
}

现在,要解决您的问题:

  

我想要做的是总结初始键范围的所有值

请注意,如果按顺序添加值,它们将在数组中按顺序排列。如果不是这种情况,请事先对数组进行排序,然后执行以下操作:

$sum = array_sum(array_slice($arr, 0, $n));

希望这有帮助!

答案 1 :(得分:3)

不幸的是,PHP数组map / reduce函数只映射值而不是键。如果您的地图使用PHP key => value数组,则需要一些技巧来过滤掉其键具有特定值的值。最简单的是直接循环:

$map = array(1 => 20, 2 => 30, 3 => -10, ...);
$n = 3;

$result = 0;
foreach ($map as $key => $value) {
    if ($key <= $n) {
        $result += $value;
    }
}

从这里你当然可以发挥创意:

$result = array_sum(array_intersect_key(
    $map,
    array_flip(array_filter(array_keys($map), function ($key) use ($n) {
        return $key <= $n;
    }))
));

或者:

$result = array_sum(array_map(function ($key, $value) use ($n) {
    return $key <= $n ? $value : 0;
}, array_keys($map), $map));

如果您正在使用更像C ++的地图,这在PHP中将是一个数组数组,这可以简化问题:

$map = array(array('key' => 1, 'value' => 20), array(...), ...);

$result = array_reduce($map, function ($v, $m) use ($n) {
    return $v + ($m['key'] <= $n ? $m['value'] : 0);
});

答案 2 :(得分:2)

嗯,有array_reduce,地图基本上只是一个数组。因此:

$result = array_reduce($your_array, function($a, $b) { return $a + $b; });

应该做的伎俩。或者只使用array_sum(谢谢,deceze)。