-1

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)
2
  • 1
    What you have tried for it?? Commented May 4, 2017 at 13:56
  • You can use array_walk to iterate through with a callback and pass the original array as the "userdata" third parameter so you can do the calculation. Give it a try and see what you come up with. Commented May 4, 2017 at 13:58

1 Answer 1

2

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]
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you. The foreach() version works great. The array_walk() version seems to work but the first value of the original array stays the same instead of being set to 0.
@r1pster I have refined my answer since you accepted. Please review the method options and select the one that you prefer for your project. I recommend array_walk().

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.