Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Porting a C++ map with std::accumulate to PHP

Tags:

c++

php

map

porting

I'm not terribly well versed with array manipulation in PHP, so I have a simple porting question. In C++ I have a map std::map<int, int>, for which the implicit ordering on the key is a crucial part of the structure. What I want to do is to sum up all the values for an initial range of keys, which I do like this:

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

What would be an idiomatic way to write this data structure and accumulator in PHP?

To explain the context: The data structure is a simple time series, and I want to know how much I have accumulated at time N. The C++ map is always sorted by key, so I can add elements mymap[time] = value; in any order, and the map always contains the elements in time order.

To explain the accumulation: The accumulate function sums up all the map's values whose keys are no greater than N. For example, take this map:

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

Then for N = 2 I accumulate 50, for N = 3 I accumulate 40, and for N = 12 I accumulate 55.


Update: I just realized that actually there's no reason why each timestamp should occur only once, so the data structure should really be a std::multimap<int, int>. The same accumulation function works verbatim, but if the PHP solution requires the time to be an array key, than that would no longer work. But this is not strictly important; I believe a solution in which each time is required to be unique will suffice.

like image 264
Kerrek SB Avatar asked Sep 03 '11 14:09

Kerrek SB


1 Answers

I'm not super familiar with C++, but I'll try to give you a quick overview of arrays in PHP, then answer your question about summing.

Every array in PHP can be thought of as an ordered map. Unlike C++, there are no restrictions on type, an array is simply a map from key to value.

To create an array, you can use the following:

$arr = array();

To add items to the array, there are two ways to do it. First, you can use the [] operator to add a new element on to the end of the array. The key for this element will be (highest int key + 1), with the first key starting at zero. For example:

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

At this point, $arr is now a map with the following keys / values:

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

We can also add specific keys and values:

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

At this point the map will look as follows:

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

There's quite a few functions built in to PHP for working with arrays. For example, there are functions for sorting arrays (both by key and value, and in user defined ways), combining arrays, searching arrays, applying functions to all elements, reducing arrays, etc. Furthermore, the PHP construct foreach can be used to iterate over an array. Use it as follows:

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

Now, to address your question:

What I want to do is to sum up all the values for an initial range of keys

Take note that if you add values in order, they will be in order in the array. If this is not the case, sort the array beforehand, then do the following:

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

Hope this helps!

like image 145
mfonda Avatar answered Sep 27 '22 20:09

mfonda