I have a PHP array which contains numbers in the following format:
$data = array(2,4,3,12,11,1,5);
Is there an easy way to obtain a second array showing the differences of these elements as T-1 (setting 0 for the first)?
The new array would look like:
$data = array(0,2,-1,9,-1,-10,4)
For this iterative subtraction process, the minuend is each value in the array. The suptrahend is the previous value (or when no previous value, the first value in the array). Because the first element's value and its suptrahend are always equal, the first value in the result is always zero.
All methods below will use the input array: $data = array(2,4,3,12,11,1,5);
When accessing the first element to declare the initial suptrahend, I used current($data)
even though $data[0]
would work, avoids a function call, and requires fewer characters. This is to make my method more robust and suitable for processing arrays which do not begin with index 0
.
Here is the array_walk() version:
array_walk($data,function(&$v,$k)use($data){$v-=($k==0?$v:$data[$k-1]);});
var_export($data);
// $result=[0,2,-1,9,-1,-10,4]
The array_walk()
method can be considered the best option because it doesn't create a $result
array, nor does it need to declare a $last
variable to preserve the previously iterated element's value. Just be aware that you cannot squeeze the array_walk()
line inside of var_export()
-- this will return true
.
This is the foreach() version:
foreach($data as $k=>$v){
$result[]=$v-($k==0?$v:$data[$k-1]);
}
var_export($result);
// $result=[0,2,-1,9,-1,-10,4]
array_reduce()
allows the declaration of an initial suptrahend via the 3rd function parameter. Here is the array_reduce() version:
array_reduce($data,function($v1,$v2)use(&$result,&$last){$result[]=$v2-(is_null($v1)?$last:$v1); $last=$v2;},current($data));
var_export($result);
// $result=[0,2,-1,9,-1,-10,4]
Here is the array_map() version:
$last=current($data);
array_map(function($v)use(&$result,&$last){$result[]=$v-$last; $last=$v;},$data);
var_export($result);
// $result=[0,2,-1,9,-1,-10,4]
// OR
// array_map(function($v,$k)use(&$result,$data){$result[]=$v-($k==0?$v:$data[$k-1]);},$data,array_keys($data));
// var_export($result);
// $result=[0,2,-1,9,-1,-10,4]
Here is the array_filter() version:
$last=current($data);
array_filter($data,function($v)use(&$last,&$result){$result[]=$v-$last; $last=$v;});
// $result=[0,2,-1,9,-1,-10,4]
// OR
// array_filter($data,function($v,$k)use(&$result,$data){$result[]=$v-($k==0?$v:$data[$k-1]);},ARRAY_FILTER_USE_BOTH);
// var_export($result);
// $result=[0,2,-1,9,-1,-10,4]