Combining array index values in php - php

I have an array of coordinates that I have extracted from JSON. Only issue I have is each index has a part of each set of coordinates. If this sounds confusing let me explain further. So basically for usage on google maps you have two parts to each set of coordinates usually separated by a comma i.e. 50.192847,-0.837228 (just an example). Problem I've got is somehow the two parts have ended up in different indexes for example:
array[0] = '50.192847'
array[1] = '-0.837228'
array[2] = '53.998772'
array[3] = '2.337622'
I think you get the idea. So my question is how do I combine each pair of indexes to make up each set of coordinates? So again for example combine array[0] and array[1] together. Is there a loop that can do this or a PHP array function of some sort?
Thanks in advance for the help!

Split to pairs and implode with comma
$array[0] = '50.192847';
$array[1] = '-0.837228';
$array[2] = '53.998772';
$array[3] = '2.337622';
foreach (array_chunk($array, 2) as $coords)
echo implode(',', $coords) . "\n";
result
50.192847,-0.837228
53.998772,2.337622

You could use a loop to start at every second key.
$newArray = array();
for($i = 0; $i < count($array) - 1 && count($array) % 2 == 0; $i = $i + 2) {
$newArray[] = $array[$i] . ',' . $array[$i + 1];
}

Related

Efficiently pick n random elements from PHP array (without shuffle)

I have the following code to pick $n elements from an array $array in PHP:
shuffle($array);
$result = array_splice($array, 0, $n);
Given a large array but only a few elements (for example 5 out of 10000), this is relatively slow, so I would like to optimize it such that not all elements have to be shuffled. The values must be unique.
I'm looking fo the most performant alternative. We can assume that $array has no duplicates and is 0-indexed.
$randomArray = [];
while (count($randomArray) < 5) {
$randomKey = mt_rand(0, count($array)-1);
$randomArray[$randomKey] = $array[$randomKey];
}
This will provide exactly 5 elements with no duplicates and very quickly. The keys will be preserved.
Note: You'd have to make sure $array had 5 or more elements or add some sort of check to prevent an endless loop.
This function performs a shuffle on only $n elements where $n is the number of random elements you want to pick. It will also work on associative arrays and sparse arrays. $array is the array to work on and $n is the number of random elements to retrieve.
If we define the $max_index as count($array) - 1 - $iteration.
It works by generating a random number between 0 and $max_index. Picking the key at that index, and replacing its index with the value at $max_index so that it can never be picked again, as $max_index will be one less at the next iteration and unreachable.
In summary this is the Richard Durstenfeld's Fisher-Yates shuffle but operating only on $n elements instead of the entire array.
function rand_pluck($array, $n) {
$array_keys = array_keys($array);
$array_length = count($array_keys);
$max_index = $array_length -1;
$iterations = min($n, $array_length);
$random_array = array();
while($iterations--) {
$index = mt_rand(0, $max_index);
$value = $array_keys[$index];
$array_keys[$index] = $array_keys[$max_index];
array_push($random_array, $array[$value]);
$max_index--;
}
return $random_array;
}
The trick is to use a variation of shuffle or in other words a partial shuffle.
performance is not the only criterion, statistical efficiency, i.e unbiased sampling is as important (as the original shuffle solution is)
function random_pick( $a, $n )
{
$N = count($a);
$n = min($n, $N);
$picked = array_fill(0, $n, 0); $backup = array_fill(0, $n, 0);
// partially shuffle the array, and generate unbiased selection simultaneously
// this is a variation on fisher-yates-knuth shuffle
for ($i=0; $i<$n; $i++) // O(n) times
{
$selected = mt_rand( 0, --$N ); // unbiased sampling N * N-1 * N-2 * .. * N-n+1
$value = $a[ $selected ];
$a[ $selected ] = $a[ $N ];
$a[ $N ] = $value;
$backup[ $i ] = $selected;
$picked[ $i ] = $value;
}
// restore partially shuffled input array from backup
// optional step, if needed it can be ignored, e.g $a is passed by value, hence copied
for ($i=$n-1; $i>=0; $i--) // O(n) times
{
$selected = $backup[ $i ];
$value = $a[ $N ];
$a[ $N ] = $a[ $selected ];
$a[ $selected ] = $value;
$N++;
}
return $picked;
}
NOTE the algorithm is strictly O(n) in both time and space, produces unbiased selections (it is a partial unbiased shuffling) and produces output which is proper array with consecutive keys (not needing extra array_values etc..)
Use example:
$randomly_picked = random_pick($my_array, 5);
// or if an associative array is used
$randomly_picked_keys = random_pick(array_keys($my_array), 5);
$randomly_picked = array_intersect_key($my_array, array_flip($randomly_picked_keys));
For further variations and extensions of shuffling for PHP:
PHP - shuffle only part of an array
PHP shuffle with seed
How can I take n elements at random from a Perl array?
This will only show benifits for small n compared to an array shuffle, but you could
Choose a random index r n times, each time decreasing the limit by 1
Adjust for previously used indices
Take value
Store used index
Pseudocode
arr = []
used = []
for i = 0..n-1:
r = rand 0..len-i
d = 0
for j = 0..used.length-1:
if r >= used[j]:
d += 1
arr.append($array[r + d])
used.append(r)
return arr
You could generate n-times a random number with mt_rand() and then fill these values in a new array. To go against the case where the same index gets returned twice we use the actual returned index to fill the new array and check always if the index exists in the new array, if so we use while to loop through it as long as we get a duplicate index. At the end we use array_values() to get a 0-indexed array.
$count = count($array) - 1;
$new_array = array();
for($i = 0; $i < $n; $i++) {
$index = mt_rand(0, $count);
while(isset($new_array[$index])) {
$index = mt_rand(0, $count);
}
$new_array[$index] = $array[$index];
}
$new_array = array_values($new_array);
I wonder why everyone here make it so complicated?
Here's the fastest and simplest way:
$randomArray = array_rand(array_flip($array), $n);

PHP put several arrays in one separated by ","

I have some arrays extracted from a XML-file. These are in
$array0 = (.......)
$array1 = (.......)
...
$arrayN = (.......)
Now I need a single array with all arrays in it separated by "," as
$masterArray = array($array0,
$array1,
...
$arrayN)
I tried
for ( $i = 0; $i < N; $i++) {
$masterArray = $masterArray + $array[$i];
}
with no result. I tried array_merge but this will give one
$masterArray(......................all items of all $arrays.....)
How can I do it right?
for ( $i = 0; $i < N; $i++) {
$temp = "array".$i;
$masterArray[$i] = ${$temp};
}
Given your exact definition of what you got and what you want the routine should be:
for ( $i = 0; $i < N; $i++) $masterArray[] = ${'array'.$i};
Not much to explain here. You make a new entry in an array with $variable[] = <entry>; and you access your numbered array with a variable variable, see:
http://php.net/manual/en/language.variables.variable.php
I guess you wont to create a multi dimension array:
$masterArray = array();
$masterArray[] = $array0;
$masterArray[] = $array1;
...
$masterArray[] = $arrayN;
this will in all arrays as element of the MasterArray:
$masterArray[0=>(....),1=>(....), ...];
Then access it like this:
$arr1_key1 = $masterArray[1]['key1'] ; //$array1['key1'];
You can add specific keys if you wont:
$masterArray['arr1'] = $array1;
$arr1_key1 = $masterArray['arr1']['key1'] ; //$array1['key1']
In general read some more to get better understanding on how to work with arrays ;)

multi-dimension array duplicate - performance

What is the best way to check if an multi-dimension array contains 2 or more equal value and only return the first one .
ex : i have an array of people that contain
[0][firstName] = 'John';
[0][lastName] = 'Doe';
[N][firstName] = 'Marco';
[N][lastName] = 'Polo';
[120][firstName] = 'John';
[120][lastName] = 'Doe';
Should detect that the index 120 is a duplicate and remove it .
I'm looking for the best performance , i don't want to loop on the array and check every time if i have the value or not .
Is there something faster ?
It is the element distinctness problem which is basically O(NlogN) via sorting and iterating (after sorting, duplicates will be adjacent to each other - so easy to detect them)
However, it can be done also in O(N) on average and with O(N) additional space by storing all elements to a hash table while iterating, and breaking if an element already exists.
You might also want to store the original index of each element if you will later need it (and don't use the index as key).
pseudo code:
map <- empty hash map
for each element e with idx i in list (in ascending order of i):
if (map.contains(e)):
e is a dupe, the first element is in index map.get(e)
else:
map.add(e,i)
You can try
// Generate Possible name with duplicate
$names = array("John","Doe","Polo","Marco","Smith");
$array = array();
for($i = 0; $i < 20; $i ++) {
$key = mt_rand(0, 1000);
$array[$key]["firstName"] = $names[array_rand($names)];
$array[$key]["lastName"] = $names[array_rand($names)];
}
// Start Sorting process
ksort($array);
// Start Storage
$data = $hash = array();
// Loop and porpulate new array
foreach ( $array as $k => $v ) {
$h = sha1($v['firstName'] . $v["lastName"]);
isset($hash[$h]) or $data[$k] = $v and $hash[$h] = 1;
}
var_dump($data);

PHP Array.length for a two dimensional array (y axis)

I am trying to use a function whereby I see how tall (y axis) a two dimensional array is in PHP. How would you suggest that I do this? Sorry, I am new to PHP.
max(array_map('count', $array2d))
If the y-axis is the outer array, then really just count($array). The second dimension would just be count($array[0]) if it's uniform.
A multi-dimensional array is simply an array of arrays -- it's not like you've blocked out a rectangular set of addresses; more like a train where each car can be stacked as high as you like.
As such, the "height" of the array, presumably, is the count of the currently largest array member. #phihag has given a great way to get that (max(array_map(count, $array2d))) but I just want to be sure you understand what it means. The max height of the various arrays within the parent array has no effect on the size or capacity of any given array member.
$max = 0;
foreach($array as $val){
$max = (count($val)>$max?count($val):$max)
}
where $max is the count you are looking for
In my application I have used this approach.
$array = array();
$array[0][0] = "one";
$array[0][1] = "two";
$array[1][0] = "three";
$array[1][1] = "four";
for ($i=0; isset($array[$i][1]); $i++) {
echo $array[$i][1];
}
output: twofour
Probably, this is not the best approach for your application, but for mine it worked perfectly.
To sum up the second dimension, use count in a loop:
$counter = 0;
foreach($var AS $value) {
$counter += count($value);
}
echo $counter;
1.dimension:
count($arr);
2.dimension:
function count2($arr) {
$dim = 0;
foreach ($arr as $v) {
if (count($v) > $dim)
$dim = count($v);
}
return $dim;
}
As it is possible to have each array / vector of different length (unlike a mathematical matrix) you have to look for the max. length.

How to Remove Array Element and Then Re-Index Array?

I have some troubles with an array. I have one array that I want to modify like below. I want to remove element (elements) of it by index and then re-index array. Is it possible?
$foo = array(
'whatever', // [0]
'foo', // [1]
'bar' // [2]
);
$foo2 = array(
'foo', // [0], before [1]
'bar' // [1], before [2]
);
unset($foo[0]); // remove item at index 0
$foo2 = array_values($foo); // 'reindex' array
array_splice($array, 0, 1);
http://php.net/manual/en/function.array-splice.php
You better use array_shift(). That will return the first element of the array, remove it from the array and re-index the array. All in one efficient method.
array_splice($array, array_search(array_value, $array), 1);
2020 Benchmark in PHP 7.4
For these who are not satisfied with current answers, I did a little benchmark script, anyone can run from CLI.
We are going to compare two solutions:
unset() with array_values() VS array_splice().
<?php
echo 'php v' . phpversion() . "\n";
$itemsOne = [];
$itemsTwo = [];
// populate items array with 100k random strings
for ($i = 0; $i < 100000; $i++) {
$itemsOne[] = $itemsTwo[] = sha1(uniqid(true));
}
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
unset($itemsOne[$i]);
$itemsOne = array_values($itemsOne);
}
$end = microtime(true);
echo 'unset & array_values: ' . ($end - $start) . 's' . "\n";
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
array_splice($itemsTwo, $i, 1);
}
$end = microtime(true);
echo 'array_splice: ' . ($end - $start) . 's' . "\n";
As you can see the idea is simple:
Create two arrays both with the same 100k items (randomly generated strings)
Remove 10k first items from first array using unset() and array_values() to reindex
Remove 10k first items from second array using array_splice()
Measure time for both methods
Output of the script above on my Dell Latitude i7-6600U 2.60GHz x 4 and 15.5GiB RAM:
php v7.4.8
unset & array_values: 29.089932918549s
array_splice: 17.94264793396s
Verdict: array_splice is almost twice more performant than unset and array_values.
So: array_splice is the winner!
Unset($array[0]);
Sort($array);
I don't know why this is being downvoted, but if anyone has bothered to try it, you will notice that it works.
Using sort on an array reassigns the keys of the the array. The only drawback is it sorts the values.
Since the keys will obviously be reassigned, even with array_values, it does not matter is the values are being sorted or not.
Try with:
$foo2 = array_slice($foo, 1);
After some time I will just copy all array elements (excluding these unwanted) to new array

Categories