Find values in PHP Array and calculate - php

I am trying to make a function where I get data from specific positions in an array, and then add(plus) the results together. Something like this:
$specificPositionsInArray = "1,4,12,27,40,42,48,49,52,53,56,58";
$dataArray = "1,2,3,4,5,6,7,8"; // More than hundred values.
myfunction($specificPositionsInArray) {
// Find position in array, based on $specificPositionsInArray and then
// plus the value with the previous value
// that is found in the $specificPositionsInArray.
// Something like:
$value = $value + $newValue;
return $value;
}
So if $specificPositionsInArray was 1,3,5
The $value that should be returned would be: 9 (1+3+5) (based on the $dataArray).
Maybe there is another way to do it, like without the function.

Here's a functional approach:
$specificPositionsInArray = array(1,3,7,6);
$dataArray = array(1,2,3,4,5,6,7,8);
function totalFromArrays($specificPositionsInArray, $dataArray) {
foreach ($specificPositionsInArray as $s){
$total += $dataArray[$s];
}
return $total;
}
$total = totalFromArrays($specificPositionsInArray, $dataArray);
echo $total;

You should look into arrays and how to handle them, you could have found the solution pretty easily. http://www.php.net/manual/en/book.array.php
//$specificPositionsInArray = array(1,4,12,27,40,42,48,49,52,53,56,58);
$specificPositionsInArray = array(1,3,5);
$dataArray = array(1,2,3,4,5,6,7,8);
$total=0;
foreach($specificPositionsInArray as $k => $v){
$total += $dataArray[$v-1];
}
echo $total;
The weird part about this is the $v-1 but because of how you want to handle the addition of the items, and an array starts with element 0, you have to subtract 1 to get to the right value.

So you want to do something like this:
$dataArray = array(1,2,3,4,5...); // 100+ values, not necessarily all integers or in ascending order
$specificPositions = array(1, 3, 5);
function addSpecificPositions($data, $positions) {
$sum = 0;
foreach($positions as $p)
$sum += $data[$p];
return $sum;
}
If you really want to keep your list of values in a string (like you have it in your example), you'll have to do an explode first to get them in array form.

Since it looks like your array is using numeric values for the keys this should be fairly easy to calculate. I refactored your code a little to make it easier to read:
$specificPositionsInArray = array(1,4,6,7);
By default PHP will assign numeric keys to each value in your array, so it will look like this to the interpreter.
array(
[0] => 1,
[1] => 4,
[2] => 6,
[3] => 7
)
This is the same for all arrays unless you specify a numeric or mixed key. Since the data array seems to just be values, too, and no keys are specified, you can simply target them with the key that they will be associated with. Say I use your array example:
$dataArray = array(1,2,3,4,5,6,7,8);
This will look like this to the parser:
array(
[0] => 1,
[1] => 2,
[2] => 3,
[3] => 4,
[4] => 5,
[5] => 6,
[6] => 7,
[7] => 8
)
If you wanted to select the number 6 from this array, you actually need to use $dataArray[5] since array keys start at zero. So for your function you would do this:
$specificPositionsInArray = array(1,4,6,7);
$dataArray = array(1,2,3,4,5,6,7,8);
calculate_array($specificPositionsInArray, $dataArray); // Returns 18
function calculate_array($keys, $data){
$final_value = 0; // Set final value to 0 to start
// Loop through values
foreach($keys as $key){
// Add the keys to our starting value
$final_value += $data[$key-1]; // minus 1 from key so that key position is human readable
}
// return the sum of the values
return $final_value;
}

Related

How can I combine consecutive keys of an array depending on their values?

I have an array similar to this:
$stuff = array("a"=>"115","b"=>"0","c"=>"1","d"=>"0","e"=>"11","f"=>"326","g"=>"9","h"=>"1","i"=>"12","j"=>"0","k"=>"56");
What I want to do is concatenate the strings of the keys only where they are consecutive and their values are under 10 - note this includes keeping solitary keys with values under 10 too. I don't need to keep the actual values. In other words, the desired result in this case would be:
Array ( [0] => bcd [1] => gh [2] => j)
So there might be just two consecutive keys that need to be joined, or there might be more (eg as many as 5). I'm not sure how to 'look ahead' through the array to achieve this.
You don't need to look ahead but keep the past in mind.
$consecutive = '';
foreach($stuff as $k => $v) {
if ($v < 10) // or what ever condition you need
$consecutive .= $k;
else {
if ($consecutive) $res[] = $consecutive; // if exist add it
$consecutive= ''; // and reset
}
}
if ($con) $res[] = $con; //adding last element if exist as #Joffrey comment
Now $res will be your desire output
Live example: 3v4l

How to output an array starting from the value with the highest character match count in php

I have been trying to match a string with the values in an array and output the array strings starting from the string with the highest character match count. for example:
$array = array(
'mike'=>'book21',
'ben'=>'buzz',
'jack'=>'airdrone',
'july'=>'march',
'fred'=>'blend45'
);
$string = 'blenmaio2';
As you can see, 'blend45', has the highest matched characters, with a total of 4 matched characters. I want to be able to output them starting from the first four highest match count, here is an example of the output i want:
blend45
book21
march
buzz
This is my first time trying to help someone, so hopefully this does the trick. I know you can probably simplify the code a little, but this is what I have.
<?php
$array = array(
'mike'=>'book21',
'ben'=>'buzz',
'jack'=>'airdrone',
'july'=>'march',
'fred'=>'blend45'
);
$string = 'blenmaio2';
$sort_array=array(); //Empty array
foreach ($array as $key => $value){
$num = similar_text($value,$string); //Using similar text to compar the strings.
$sort_array[$value] = $num; //Adding the compared number value and sring value to array.
}
arsort($sort_array, SORT_REGULAR);//Sorting the array by the larges number.
print_r ($sort_array);
//creating another foreach statement to get the output you wanted.
$count = 0;
foreach($sort_array as $key => $value){
$count++;
echo $count.". ".$key."\n";
};
?>
Results:
Array
(
[blend45] => 4
[book21] => 3
[airdrone] => 3
[march] => 2
[buzz] => 1
)
1. blend45
2. book21
3. airdrone
4. march
5. buzz
I think the levenshtein() function would be the most appropriate method to achieve your goal:
$array = array(
'mike'=>'book21',
'ben'=>'buzz',
'jack'=>'airdrone',
'july'=>'march',
'fred'=>'blend45'
);
$string = 'blenmaio2';
uasort($array, function($a, $b) use ($string) {
$aDistance = levenshtein($string, $a);
$bDistance = levenshtein($string, $b);
return ($aDistance < $bDistance) ? -1 : 1;
});
print_r($array);
// Output:
// Array
// (
// [fred] => blend45
// [july] => march
// [mike] => book21
// [ben] => buzz
// [jack] => airdrone
// )
http://php.net/levenshtein
Update Use uasort() instead of usort() to preserve the array keys.
I just noticed that my answer compares the similarity, but doesn't meet the highest character count match, so sorry for that :)
Here you are my answer. It is a bit different, because I'm using levenshtein function for finding nearest between two words.
I'm using uasort to reorder the array in way you liked.
Of course you can replace the algorithm for nearest by your function.
<?php
$array = array(
'mike'=>'book21',
'ben'=>'buzz',
'jack'=>'airdrone',
'july'=>'march',
'fred'=>'blend45'
);
$string = 'blenmaio2';
function cmp($a,$b){
global $string;
$aa=levenshtein($a, $string);
$bb=levenshtein($b, $string);
if($aa>$bb)
return 1;
elseif($bb>$aa)
return -1;
else return 0;
}
uasort($array,cmp);
?>
<pre><?= print_r($array); ?></pre>

PHP: How to delete all array elements after an index [duplicate]

This question already has answers here:
php - how to remove all elements of an array after one specified
(3 answers)
Closed 9 years ago.
Is it possible to delete all array elements after an index?
$myArrayInit = array(1=>red, 30=>orange, 25=>velvet, 45=>pink);
now some "magic"
$myArray = delIndex(30, $myArrayInit);
to get
$myArray = array(1=>red, 30=>orange);
due to the keys in $myArray are not successive, I don't see a chance for array_slice()
Please note : Keys have to be preserved! + I do only know the Offset Key!!
Without making use of loops.
<?php
$myArrayInit = [1 => 'red', 30 => 'orange', 25 => 'velvet', 45 => 'pink']; //<-- Your actual array
$offsetKey = 25; //<--- The offset you need to grab
//Lets do the code....
$n = array_keys($myArrayInit); //<---- Grab all the keys of your actual array and put in another array
$count = array_search($offsetKey, $n); //<--- Returns the position of the offset from this array using search
$new_arr = array_slice($myArrayInit, 0, $count + 1, true);//<--- Slice it with the 0 index as start and position+1 as the length parameter.
print_r($new_arr);
Output :
Array
(
[1] => red
[30] => orange
[25] => velvet
)
Try
$arr = array(1=>red, 30=>orange, 25=>velvet, 45=>pink);
$pos = array_search('30', array_keys($arr));
$arr= array_slice($arr,0,$pos+1,true);
echo "<pre>";
print_r($arr);
See demo
I'd iterate over the array up until you reach the key you want to truncate the array thereafter, and add those items to a new - temporary array, then set the existing array to null, then assign the temp array to the existing array.
This uses a flag value to determine your limit:
$myArrayInit = array(1=>'red', 30=>'orange', 25=>'velvet', 45=>'pink');
$new_array = delIndex(30,$myArrayInit);
function delIndex($limit,$array){
$limit_reached=false;
foreach($array as $ind=>$val){
if($limit_reached==true){
unset($array[$ind]);
}
if($ind==$limit){
$limit_reached=true;
}
}
return $array;
}
print_r($new_array);
Try this:
function delIndex($afterIndex, $array){
$flag = false;
foreach($array as $key=>$val){
if($flag == true)
unset($array[$key]);
if($key == $afterIndex)
$flag = true;
}
return $array;
}
This code is not tested

PHP: duplicate value removal

I have 2 arrays with for example 1000 key's each, one holds a temperature value and the other the hour.
Example array temp:
[0] = 3.1
[1] = 4.3
[2] = 4.1
[3] = 5.1
[4] = 4.1
Example hour array:
[0] = 0
[1] = 1
[2] = 2
[3] = 3
[4] = 3
The problem with this is that when i combine these to arrays and plot this in for example pchart i have too many values on the X and it gets cluttered.
So what i need to to remove the duplicate hours and replace then with "NULL", so that the unneeded hours are not plotted on the x axis.
I want to keep the first hour in the array, the second to the end of the duplicates can be set to "NULL"
The hour output array should be:
[0] = 0
[1] = 1
[2] = 2
[3] = 3
[4] = NULL
etc.
Sounds like a job for array_unique().
array array_unique ( array $array [, int $sort_flags = SORT_STRING ] )
Takes an input array and returns a new array without duplicate values.
Note that keys are preserved. array_unique() sorts the values treated
as string at first, then will keep the first key encountered for every
value, and ignore all following keys. It does not mean that the key of
the first related value from the unsorted array will be kept.
Note: Two elements are considered equal if and only if (string) $elem1
=== (string) $elem2. In words: when the string representation is the same. The first element will be used.
If you require the array keys to persist, you can try something with array_map().
<?php
//Variable initialization
$array = array(
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 3
);
$temp = array();
$array = array_map(function($element) use (&$temp) {
if (!in_array($element, $temp)) {
$temp[] = $element;
return $element;
}
return null;
}, $array);
print_r($array);
Your array is sorted, so... how about this?
$hours = array(0,1,2,3,3,4,4,5);
$prev = -1;
foreach ($hours as &$hour) {
if ($prev === $hour) {
$hour = NULL;
}
else {
$prev = $hour;
}
}
unset($hour);
print_r($hours); // 0,1,2,3,NULL,4,NULL,5...
If you're using php 5.3:
$a = array(0,1,2,3,4,4,5);
array_walk($a, function(&$item) {
static $encountered = array();
if(in_array($item, $encountered)) {
$item = null;
return;
}
$encountered[] = $item;
});
var_dump($a);
Will preserve the number of keys. Array_walk calls a user function for every key. static makes it so that the $encountered array in the scope of the function stays between executions.
If you want to remove the duplicates entirely you can use array_unique()
but it wont set them to NULL.
Maybe this trick does it:
$simplified = array_combine($hours, $temperatures);
$hours = array_keys($simplified);
$temperatures = array_values($simplified);
This won't set things to NULL but to completely remove them which I think is what you're looking for. Otherwise this should do it:
foreach(array_slice(array_reverse(array_keys($hours)), 0, -1) as $i)
($hours[$i] === $hours[$i-1]) && $hours[$i] = NULL;
Demo

Rotate array elements to the left (move first element to last and re-index)

Is it possible to easily 'rotate' an array in PHP?
Like this:
1, 2, 3, 4 -> 2, 3 ,4 ,1
Is there some kind of built-in PHP function for this?
$numbers = array(1,2,3,4);
array_push($numbers, array_shift($numbers));
print_r($numbers);
Output
Array
(
[0] => 2
[1] => 3
[2] => 4
[3] => 1
)
Most of the current answers are correct, but only if you don't care about your indices:
$arr = array('foo' => 'bar', 'baz' => 'qux', 'wibble' => 'wobble');
array_push($arr, array_shift($arr));
print_r($arr);
Output:
Array
(
[baz] => qux
[wibble] => wobble
[0] => bar
)
To preserve your indices you can do something like:
$arr = array('foo' => 'bar', 'baz' => 'qux', 'wibble' => 'wobble');
$keys = array_keys($arr);
$val = $arr[$keys[0]];
unset($arr[$keys[0]]);
$arr[$keys[0]] = $val;
print_r($arr);
Output:
Array
(
[baz] => qux
[wibble] => wobble
[foo] => bar
)
Perhaps someone can do the rotation more succinctly than my four-line method, but this works anyway.
It's very simple and could be done in many ways. Example:
$array = array( 'a', 'b', 'c' );
$array[] = array_shift( $array );
Looping through the array, and shift-ing and push-ing, may be a common way to rotate an array, however it can often mess up your keys. A more robust method is using a combination of array_merge and array_splice.
/**
* Rotates an array.
*
* Numerical indexes will be renumbered automatically.
* Associations will be kept for keys which are strings.
*
* Rotations will always occur similar to shift and push,
* where the number of items denoted by the distance are
* removed from the start of the array and are appended.
*
* Negative distances work in reverse, and are similar to
* pop and unshift instead.
*
* Distance magnitudes greater than the length of the array
* can be interpreted as rotating an array more than a full
* rotation. This will be reduced to calculate the remaining
* rotation after all full rotations.
*
* #param array $array The original array to rotate.
* Passing a reference may cause the original array to be truncated.
* #param int $distance The number of elements to move to the end.
* Distance is automatically interpreted as an integer.
* #return array The modified array.
*/
function array_rotate($array, $distance = 1) {
settype($array, 'array');
$distance %= count($array);
return array_merge(
array_splice($array, $distance), // Last elements - moved to the start
$array // First elements - appended to the end
);
}
// Example rotating an array 180°.
$rotated_180 = array_rotate($array, count($array) / 2);
Alternatively, if you also find the need to rotate keys so that they match with different values, you can combine array_keys, array_combine, array_rotate, and array_values.
/**
* Rotates the keys of an array while keeping values in the same order.
*
* #see array_rotate(); for function arguments and output.
*/
function array_rotate_key($array, $distance = 1) {
$keys = array_keys((array)$array);
return array_combine(
array_rotate($keys, $distance), // Rotated keys
array_values((array)$array) // Values
);
}
Or alternatively rotating the values while keeping the keys in the same order (equivalent to calling the negative distance on the matching array_rotate_key function call).
/**
* Rotates the values of an array while keeping keys in the same order.
*
* #see array_rotate(); for function arguments and output.
*/
function array_rotate_value($array, $distance = 1) {
$values = array_values((array)$array);
return array_combine(
array_keys((array)$array), // Keys
array_rotate($values, $distance) // Rotated values
);
}
And finally, if you want to prevent renumbering of numerical indexes.
/**
* Rotates an array while keeping all key and value association.
*
* #see array_rotate(); for function arguments and output.
*/
function array_rotate_assoc($array, $distance = 1) {
$keys = array_keys((array)$array);
$values = array_values((array)$array);
return array_combine(
array_rotate($keys, $distance), // Rotated keys
array_rotate($values, $distance) // Rotated values
);
}
It could be beneficial to perform some benchmark tests, however, I expect that a small handful of rotations per request wouldn't affect performance noticeably regardless of which method is used.
It should also be possible to rotate an array by using a custom sorting function, but it would most likely be overly complicated. i.e. usort.
A method to maintain keys and rotate. using the same concept as array_push(array, array_shift(array)), instead we will use array_merge of 2 array_slices
$x = array("a" => 1, "b" => 2, "c" => 3, 'd' => 4);
To move the First element to the end
array_merge(array_slice($x, 1, NULL, true), array_slice($x, 0, 1, true)
//'b'=>2, 'c'=>3, 'd'=>4, 'a'=>1
To move the last element to the front
array_merge(array_slice($x, count($x) -1, 1, true), array_slice($x, 0,
//'d'=>4, 'a'=>1, 'b'=>2, 'c'=>3
you can use this function:
function arr_rotate(&$array,$rotate_count) {
for ($i = 0; $i < $rotate_count; $i++) {
array_push($array, array_shift($array));
}
}
usage:
$xarr = array('1','2','3','4','5');
arr_rotate($xarr, 2);
print_r($xarr);
result:
Array ( [0] => 3 [1] => 4 [2] => 5 [3] => 1 [4] => 2 )
There's a task about array rotation on Hackerrank: https://www.hackerrank.com/challenges/array-left-rotation/problem.
And proposed solution with array_push and array_shift will work for all test cases except the last one, which fails due to timeout. So, array_push and array_shift will give you not the fastest solution.
Here's the faster approach:
function leftRotation(array $array, $n) {
for ($i = 0; $i < $n; $i++) {
$value = array[$i]; unset(array[$i]); array[] = $value;
}
return array;
}
Use array_shift and array_push.
$daynamesArray = array("Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday");
array_push($daynamesArray, array_shift($daynamesArray)); //shift by one
array_push($daynamesArray, array_shift($daynamesArray)); //shift by two
print_r($daynamesArray);
The output starts at "Wednesday":
Array ( [0] => Wednesday [1] => Thursday [2] => Friday [3] => Saturday [4] => Sunday [5] => Monday [6] => Tuesday
Yes it is, here is a function I did myself, where $A is the array and $K the number of times you want to rotate the array:
function solution($A, $K) {
for($i = 0; $i < $K; $i++): //we cycle $K
$arrayTemp = $A;
for($j = 0; $j < count($arrayTemp); $j++): // we cycle the array
if($j == count($arrayTemp) - 1) $A[0] = $arrayTemp[$j]; // we check for the last position
else $A[$j + 1] = $arrayTemp[$j]; // all but last position
endfor;
endfor;
return $A;
}
The logic is to swap the elements. Algorithm may look like -
for i = 0 to arrayLength - 1
swap( array[i], array[i+1] ) // Now array[i] has array[i+1] value and
// array[i+1] has array[i] value.
No. Check the documentation for array_shift and its related functions for some tools you can use to write one. There might even be an array_rotate function implemented in the comments of that page.
It's also worth reading through the array functions listed on the left-hand sidebar to get a full understanding of what array functions are available in PHP.
Here's a function to rotate an array (zero-indexed array) to any position you want:
function rotateArray($inputArray, $rotateIndex) {
if(isset($inputArray[$rotateIndex])) {
$startSlice = array_slice($inputArray, 0, $rotateIndex);
$endSlice = array_slice($inputArray, $rotateIndex);
return array_merge($endSlice, $startSlice);
}
return $inputArray;
}
$testArray = [1,2,3,4,5,6];
$testRotates = [3, 5, 0, 101, -5];
foreach($testRotates as $rotateIndex) {
print_r(rotateArray($testArray, $rotateIndex));
}
Not too dissimilar to the first snippet in ShaunCockerill's answer, I also endorse not making iterated functions calls to perform the rotation. In fact, I'll recommend using early returns to optimize performance and reduce the total number of function calls needed.
The following snippet is the "move left" version of the "move right" version that I posted here. In my demo, there is a single, static input array and the foreach() loop merely changes the desired amount of rotation (0 to 9).
Code: (Demo)
function shiftPop(array $indexedArray, int $shiftPopsCount): array
{
$count = count($indexedArray);
if ($count < 2) {
return $indexedArray;
}
$remainder = $shiftPopsCount % $count;
if (!$remainder) {
return $indexedArray;
}
return array_merge(
array_splice($indexedArray, $remainder),
$indexedArray
);
}
$array = [1, 2, 3, 4];
foreach (range(0, 9) as $moves) {
var_export(shiftPop($array, $moves));
echo "\n---\n";
}
The first if block in my snippet is not engaged by my demo because my array always has 4 elements. The second if block is engaged, when $moves is 0, 4, and 8 -- in these cases, the input is identical to the desired output, so calling array_merge() and array_splice() is pointless.

Categories