create another multi dimensional array from an array - php

Suppose i have an array
$x= ('A'=>31, 'B'=>12, 'C'=>13, 'D'=>25, 'E'=>18, 'F'=>10);
I need to generate an array somewhat like this
$newx = (0 => array('A'=>31 , 'B' =>1) , 1 => array('B'=>11 , 'C' =>13 , 'D'=>8) , 2 =>array('D'=>17 , 'E'=>15) , 3=>array('E'=>3,'F'=>10);
Now in this case each value of $newx has to be = 32 and this is how it will work $x[A] = 31 , $x[B] = 12 so first of all we have to make the sum quantity to be 32 keeping the index same for the new array i.e
array(0=>array('A'=>31,'B'=>1) , 1=>array('B'=>11) )
the process should continue for each value of $x.

while I'm pretty sure this is a homework assignment and well, you really should provide code of your own, at least try to, I found the thing amusing so I went ahead and gave it a try. I guess I'll be downvoted for his and I probably do deserve it, but here goes anyway.
What you need to do is:
loop through your array,
determine the elements that give you 32 and then store that result in the final array.
subtract the value of the last element from your result from the corresponding element of your working array
shrink your array next by deleting the first elements until the very first element of the array you're still working with equals the last element your last result returned.
if your last result < 32, quit.
With this in mind, please try to find a solution yourself first and don't just copy-paste the code? :)
<?php
$x = array('A'=>31, 'B'=>12, 'C'=>13, 'D'=>25, 'E'=>18, 'F'=>10);
$result = array();
function calc($toWalk){
// walk through the array until we have gathered enough for 32, return result as an array
$result = array();
foreach($toWalk as $key => $value){
$count = array_sum($result);
if($count >= 32){
// if we have more than 32, subtract the overage from the last array element
$last = array_pop(array_keys($result));
$result[$last] -= ($count - 32);
return $result;
}
$result[$key] = $value;
}
return $result;
}
// logic match first element
$last = 'A';
// loop for as long as we have an array
while(count($x) > 0){
/*
we make sure that the first element matches the last element of the previously found array
so that if the last one went from A -> C we start at C and not at B
*/
$keys = array_keys($x);
if($last == $keys[0]){
// get the sub-array
$partial = calc($x);
// determine the last key used, it's our new starting point
$last = array_pop(array_keys($partial));
$result[] = $partial;
//subtract last (partial) value used from corresponding key in working array
$x[$last] -= $partial[$last];
if(array_sum($partial) < 32) break;
}
/*
reduce the array in size by 1, dropping the first element
should our resulting first element not match the previously returned
$last element then the logic will jump to this place again and
just cut off another element
*/
$x = array_slice($x , 1 );
}
print_r($result);

Related

Find the first appearance of a number in associative array

Let's say the following is true:
I have an associative array containing an unknown number of elements.
The keys are integers, starting at 1, and each is one more than the last.
There is an element with key N whose value is 1.
The value of each element with a key less than N is 0.
The value of each element with a key greater than N is 1.
This is the array:
The question is :
What is the fastest/smartest way to find the position of the first '1' in the array?
If you truly don't know the length of the array (a very odd situation), then probably all you can do is grow your search geometrically, i.e. skip 4, skip 8, skip 16, etc. until you find a 1, then cut back with a (geometric) binary search.
array_search is your best bet
// Make up some data...
$data = [];
for ($i = 1; $i <= 20; ++$i) {
$data[$i] = rand(0,5);
}
var_dump($data);
// Find the first one...
echo 'The first 1 is at position: ' . array_search(1, $data);
http://php.net/manual/en/function.array-search.php

Shifting the items in an array by a specified value

How would you go about circularly rotating the items in an array up or down by a specified value. For example
$value = 1; // circularly rotate by 1
$array = array(1,2,3,4,5);
// Should return
array(2,3,4,5,1);
The entire array is circularly rotated anti-clockwise by 1. 1 went to the end and 2 became the leading number in the array. I cannot find a reliable way to do this.
Use a for-loop with a specification on how many items you want moved, and array_shift() to shift the array. Then add the first element to a shifted array (which essentially moves the first item to the last element)
$shift = 2; // How many times you want to move it
$output = array(1, 2, 3, 4, 5);
for ($i = 0; $i < $shift; $i++) {
array_push($output , array_shift($output));
}
print_r($output); // 3, 4, 5, 1, 2
Live demo
References
http://php.net/manual/en/function.array-shift.php
http://php.net/manual/en/function.array-push.php
You can combine the array_push function that adds a value to the end of an array and the array_shift function that removes and returns the first element of an array.
<?php
$value = 1; // circularly rotate by 1
$array = array(1,2,3,4,5);
while ($value) {
array_push($array, array_shift($array));
$value--;
}
print_r($array);
?>

Multidimensional sub array subtraction in PHP

Need subarray difference of below array
$arr = array(
array('s'=>'1','e'=>'3'),
array('s'=>'6','e'=>'7'),
array('s'=>'8','e'=>'9'),
array('s'=>'10','e'=>'14'),
array('s'=>'16','e'=>'17'),
)
if(arr[$arr[$i+1][s] - $i][e] <= 1){
//join them
}
else {
//save them as it is
}
Desired result should
$arr = array(
array('s'=>'1','e'=>'3'),
array('s'=>'6','e'=>'14'),
array('s'=>'16','e'=>'17'),
)
No consecutive (next S-E) should be 1
http://codepad.org/V8omMdn6 is where im struck at
See its like
iteration 0
6-3 = 3
so save array('s'=>'1','e'=>'3'),
iteration 1
8-7 = 1
array('s'=>'6','e'=>'9'), => discade in 2 as it
iteration 2
10-9 = 1
array('s'=>'6','e'=>'10'), => discade in 3 as it
iteration 3
10-9 = 1
array('s'=>'6','e'=>'14'),
iteration 4
16-14 = 4
array('s'=>'16','e'=>'17'),
$result = [];
foreach ($arr as $pair) {
if (empty($result) || $pair['s'] - end($result)['e'] > 1) {
$result[] = $pair;
} else {
$result[key($result)]['e'] = $pair['e'];
}
}
You might also use $last as key instead end() & key() for readability.
Using array pointer functions on $result shortens the code but uses some ugly hidden effects. end($result) returns last element of array (using key bracket with function result is possible since php5.3 I guess), but also sets the pointer, so key($result) will return correct key if needed.
While iterating you process last element of result array - this element might not be valid right away, but you don't need to look ahead. There are two scenarios for last element (+initial state condition for empty $result):
invalid: set e value from current item and process further
valid: leave it and push current item into results for further validation (unless that was the last one).
I took a very brief look at your codepen, I think what you want to achieve is to find out if the start time of a new session is within a given period from the end time of the last session, if so you would like to combine those sessions.
I think you confused yourself by trying to subtract start time of new session from end time of last session, it should be the other way round.
The way you worded the question made it even more confusing for people to understand.
If my interpretation of your question is correct, the below code should work with the test case you posted here.
function combineSession($arr){
$arrCount=count($arr)-1;
for ($i=0; $i<$arrCount; $i++){
//if the difference between s and e is less than or equal to one, then there is a consecutive series
if($arr[$i+1]['s']-$arr[$i]['e'] <= 1){
//assign the value of s at the start of a consecutive series to $temp
if (!isset($temp)){
$temp=$arr[$i]['s'];
}
//if consecutive series ends on the last sub_array, write $temp e pair to output
if ($i==$arrCount-1){
$output[]= array('s'=> $temp, 'e' => $arr[$arrCount]['e']);
}
}
//end of a consecutive series, write $temp and e pair to output, unset $temp
else if (isset($temp) && $i<$arrCount-1){
$output[]=array('s'=> $temp, 'e' => $arr[$i]['e']);
unset($temp);
}
//consecutive series ended at the second last sub-array, write $temp and e pair to output and copy key value pair of the last sub-array to output
else if ($i==$arrCount-1){
$output[]=array('s'=> $temp, 'e' => $arr[$i]['e']);
$output[]=$arr[$arrCount];
}
//not in a consecutive series, simply copy s e key value pair to output
else {
$output[]=$arr[$i];
}
}//end of for loop
print_r($output);
}//end of function
else if ($i==$arrCount-1){ $output[]=!isset($temp) ? $arr[$i] : array('s'=> $temp, 'e' => $arr[$i]['e']); $output[]=$arr[$arrCount]; }

Remove element and reindex

the logic is to get last element from the elemnt after particular interval when all the elemnts are been removed. suppose there are five users and every secound user is been eliminated , then i have to find the last remaining user.
$foo = array(
'0'=>'1',
'1'=>'2',
'2'=>'3',
'3'=>'4',
'4'=>'5',
'5'=>'6'
);
now remove element indexed at 2 and reindex the array in below format.
$foo = array(
'0'=>'4',
'1'=>'5',
'2'=>'6',
'3'=>'1',
'4'=>'2',
);
You can use unset(), but you'll also need to call array_values() to force a re-index. For example:
unset($foo[2]);
$foo = array_values($foo);
The original question is a bit unclear. I understand you want to remove index X, and place all items after index X as first items in the array.
$index2remove = 2;
$newArray1 = array_slice($foo, $index2remove+1); // Get items after the selected index
$newArray2 = array_slice($foo, 0, $index2remove); // get everything before the selected index
$newArray = array_merge($newArray1, $newArray2); // and combine them
Or shorter and a bit less memory consuming (but harder to read):
$index2remove = 2;
$newArray = array_merge(
array_slice($foo, $index2remove+1), // add last items first
array_slice($foo, 0, $index2remove) // add first items last
);
You do NOT need to unset value 2 in my code, you simple slice it out. We do that with the -1 in the 2nd splice function.
If you want, you can replace $newArray = array_merge() with $foo = array_merge(), but ONLY in the second, if you dont need to save the original array.
Edit: Changed small error, thank you plain jane
Try this of which the output is given below
$foo = array('0'=>'1','1'=>'2','2'=>'3','3'=>'4','4'=>'5','5'=>'6');
//need to input this as the index of the element to be removed
$remove_index = "2";
unset($foo[$remove_index]);
$slice1 = array_slice($foo, 0, $remove_index);
$slice2 = array_slice($foo, $remove_index);
$final_output = array_merge($slice2, $slice1);
Output
Array
(
[0] => 4
[1] => 5
[2] => 6
[3] => 1
[4] => 2
)

php arrays get the order number of a certain element

Lets say i have an array in PHP
$test['michael_unique_id'] = 3;
$test['john_unique_id'] = 8;
$test['mary_unique_id'] = 10;
.
.
.
.
$test['jimmy_unique_id'] = 4;
(the values (3,8,10.........4) are unique)
Lets say i want to search for the unique id 10, and get the order of the matching element in the array. In this example, the third element has the value 10, so i should get the number 3.
I can do it by scanning with a for loop looking for the value i'm searching and then get the $i value when i have a match, but i wonder if there is any built-in function (or a better method) that implements this.
You can get all of the array's values as an array with array_values() and then use array_search() to get the position (offset) of that value in the array.
$uniq_id = 10;
$all_vals = array_values($test); // => array(3, 8, 10, ... )
echo array_search( $uniq_id, $all_vals ); // => 2
Because PHP array indices are zero-based, you'll get 0 for the first item, 1 for the second item, etc. If you want the first item to be "1," then just add one. All together now:
$uniq_id = 10;
echo array_search( $uniq_id, array_values( $test ) ) + 1; // => 3
It's not clear to me, however, that this is necessarily as performant as just doing a foreach:
$uniq_id = 10;
$idx = 1;
foreach($test as $val) {
if($val == $uniq_id) {
break;
}
$idx++;
}
echo $idx; // => 3
Well, array_search will give you the key, but in your case, you want the index of that key, so I believe a loop is your best bet. Is there a good reason why you need the index? It doesn't seem very useful to me.

Categories