Push the same element x times onto the array - php

Basically I need to create this array (given x = 3)
array('?','?','?');
I could do
for($i=0;$i<3;$i++)
$arr[]='?';
But it's not so elegant. Is there any other way?

Use array_fill( start_index, num, value ):
$arr = array_fill(0, 3, '?');

To address the question of how to push the same element a number of times onto an array, it's worth noting that while array_fill() is certainly the most elegant choice for generating a new array, this is the only thing it can do. It cannot actually push elements onto an existing array.
So while a basic loop isn't particularly exciting, it does work well in situations where you have an existing array you want to add to, regardless of whether it's already empty or not.
$arr = ['a', 'a', 'a'];
for ($i = 0; $i < 3; $i++) {
$arr[] = 'b';
}
print_r($arr);
Array
(
[0] => a
[1] => a
[2] => a
[3] => b
[4] => b
[5] => b
)
To achieve the same thing with array_fill() it requires an additional merge:
$arr = array_merge($arr, array_fill(0, 3, 'b'));

Related

How to randomly select elements from an array that each element is selected only 1 time?

The following array contains entries for a competition. Some participants are shown more than others, hence the times they participate into this.
For example "pounho" has better chances than "vinylin". This is why he has more occurences than "vinylin" in the array.
My question is how to select 3 results out of the following example array, but the results must be unique, no repetitions?
Because currently, I can show 3 results, but there is repetition, for example
deou, deou, pounho.
I don't want to remove duplicates. I want the code to take into consideration that the participant "pounho" has better chances than "vinylin".
Array
(
[0] => pounho
[1] => pounho
[2] => pounho
[3] => panony
[4] => mamich
[5] => Deou
[6] => Deou
[7] => vinylin
[8] => laids
[9] => laids
)
$inputArray = [...];
$backuppedArray = $inputArray;
$randomlySelected = [];
while(count($randomlySelected) < 3 && count($backuppedArray) > 0){
$randomItem = $backuppedArray[array_rand($backuppedArray)];
if(!in_array($randomItem, $randomlySelected)){
$randomlySelected []= $randomItem;
$backuppedArray = array_diff($backuppedArray, array($randomItem));
}
}
updated answer, the more times participant is in array the more chance he has to be in random pick, it's simplest code to achieve it I could imagine
Select a random element of the array, then remove all copies of that element. Do this 3 times to get 3 different elements.
$results = array();
for ($i = 0; $i < 3; $i++) {
$index = array_rand($array);
$selected = $array[$index];
$results[] = $selected;
$array = array_diff($array, array($selected));
}
Not sure about the efficiency, especially with huge arrays, but; retrieve the first 3 values and check if they are unique. If not unique, shuffle and try again. Values with a higher frequency will have a better chance of being in the first 3:
while(count($result = array_unique(array_slice($array, 0, 3))) < 3){ shuffle($array); }
You need array_unique
$array2 = array_unique($array);
print_r($array2);
This snippet will "rank" the items in the array:
$count = array_count_values($array); //Counts values and makes new array
arsort($count); //Sort that array high to low
$keys = array_keys($count); //Split the array so we can find the key that occurs the most
echo "The top v is $keys[0][1] with $keys[0][0] occurrences."

How to cut array into two

I am trying to separate an array into two separate arrays. For example, if I have an array like this
Array([0]=>Hello[1]=>I'm[2]=>Cam)
I want to split it into two arrays and add another string
Array1([0]=>Hello[1]=>There,)
Array2([0]=>I'm[1]=>Cam)
Then finally add the two together
Array([0]=>Hello[1]=>There,[2]=>I'm[3]=>Cam)
What would be the simplest way to do this?
I know I can use array merge to put the two together but I don't know how to separate them at a certain point.
I'm also doing this on a large file that will be constantly getting bigger, so I cant use array_chunk()
Looking at your end result goal, I think a shorter method to get your desired response is to use array_splice which lets you insert into a middle of an array....
$arrayVarOriginal = array('Hello', 'Im', 'Cam');
$arrayVarExtra = array('There');
array_splice($arrayVarOriginal, 1, 0, $arrayVarExtra);
This should send you back Array([0]=>Hello[1]=>There,[2]=>Im[3]=>Cam) like you wanted!
The above avoids having to split up the array.
HOWEVER
If you did want to do it the hard way, here is how you would...
$arrayVarOriginal = array('Hello', 'Im', 'Cam');
$array1stPart = array(arrayVarOriginal[0], 'There');
$array2ndPart = array_shift($array1stPart);
$finalArray = array_merge($array1stPart, $array2ndPart);
How? array_shift removes the first item from any array, so that how we get $array2ndPart.... and $array1stPart is even easier as we can just manually build up a brand new array and take the first item from $arrayVarOriginal which is at position 0 and add 'There' in as our own new position 1.
Hope that helps :)
array_shift, array_splice, and array_merge are what you need to look into.
Based from your question, here step-by-step to get what you want for your final output.
1) Split Array
$arr = array('Hello', 'I\'m', 'Cam');
$slice = count($arr) - 1;
$arr1 = array_slice($arr, 0, -$slice);
$arr2 = array_slice($arr,1);
so, you get two new array here $arr1 and $arr2
2) Add new string
$arr1[] = "There";
3) Finally, combine the array
$arr = array_merge($arr1, $arr2)
Here sample output when you print_r the $arr
Array
(
[0] => Hello
[1] => There
[2] => I'm
[3] => Cam
)
array_slice second parameter is position where you want split. So you can do this dynamically by count the array length.
$string = array("Hello","I'm","Cam");
$firstArray = array_slice($string ,0,1);
array_push($firstArray,"There,");
$secondArray = array_slice($string ,1,2);
echo "<pre>";
print_r($firstArray);
echo "==========="."<pre>";
print_r($secondArray);
echo "<pre>";
print_r(array_merge($firstArray,$secondArray));
//out put
Array
(
[0] => Hello
[1] => There,
)
===========
Array
(
[0] => I'm
[1] => Cam
)
Array
(
[0] => Hello
[1] => There,
[2] => I'm
[3] => Cam
)
Hope it will be worked for your requirement. If not or you need more specify regarding this you can clarify your need.

Pushing random array elements into another array in PHP

I have an array consisting of N>10 URLs. I want to randomly pick 10 of them and store them in another array. How can I achieve this? Is array_rand() the way to go? If yes, then how do I ensure that there are no duplicities in the output array? Do I have to check the second array everytime a new element is added for existence?
// $firstArray is defined earlier
$secondArray = array();
array_push(array_rand($firstArray, 10));
This doesn't work unfortunately. I was thinking about using a for cycle for the array_push() but I was just curious if array_rand() can do that for me.
Thanks for advice!
array_rand returns keys so
$randKeys = array_rand($firstArray, 10);
foreach($randKeys as $key)
$secondArray[] = $firstArray[$key]
This can be done without array_rand(). Use shuffle() to shuffle the array elements and then use array_slice() to get the first 10 items:
$secondArray = array();
shuffle($firstArray);
$secondArray = array_slice($firstArray, 0, 10);
Demo!
As people said there is a second argument in array_rand() to pick how many random elements you want, always remember to read the Manual
//Lets pick 10 mammals
$mammals = array('dog', 'cat', 'pig', 'horse', 'bat', 'mouse', 'platypus', 'bear', 'donkey', 'deer', 'hog', 'duck');
$ten = array_rand(array_flip($mammals), 10);
//If what yo u really wanted is to append them to another array, let's say "animals":
$animals = array('fish', 'crab', 'whale', 'eagle');
$animals = array_merge($animals, array_rand(array_flip($mammals), 10));
Explanation
array_rand() will return you the keys, so we can use array_flip() here to reverse the keys => values positions before picking them, no need to loop through them again.
And using array_merge() we merge them together, with no need to loop through the ten random elements to add them one by one, unless ... you want a specific order or other logic.
Not very optimized solution, but for small amounts of data it may suit:
$firstArray = array(1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9);
$secondArray = array();
$tmp = array_unique($firstArray);
shuffle($tmp);
$secondArray += array_slice($tmp,0, 10);
If you use array_push like in the example code, the last index in your second array will contain the returned 10 indexes
Eg.
$stack = array('a', 'b', 'c');
array_push($stack, array('d', 'e', 'f'));
print_r($stack);
Array (
[0] => a
[1] => b
[2] => c
[3] => Array (
[0] => d
[1] => e
[2] => f
)
)
I would use a while in this case and pick only one value at a time. Something like:
$stack = array();
while(count($stack)<10){
$item = array_rand($collection_of_urls);
if(!in_array($item)
array_push($stack, $item);
}
this simple
$rand_keys = array_rand($input, 10);
print_r($rand_keys);

How to compare every element of array with one another?

I want to compare every element of array with one another.
$char=array();
for($i=0;$i<=10;$i++)
{
$char[$i]=rand(0,35);
}
I want to compare every element of $char array. If there is any value repeated than it should change value and select another random value which should be unique in array..
In this particular example, where the range of possible values is very small, it would be better to do this another way:
$allPossible = range(0, 35);
shuffle($allPossible);
// Guaranteed exactly 10 unique numbers in the range [0, 35]
$char = array_slice($allPossible, 0, 10);
Or with the equivalent version using array_rand:
$allPossible = range(0, 35);
$char = array_rand(array_flip($allPossible), 10);
If the range of values were larger then this approach would be very wasteful and you should go with checking for uniqueness on each iteration:
$char = array();
for ($i = 0; $i < 10; ++$i) {
$value = null;
// Try random numbers until you find one that does not already exist
while($value === null || in_array($value, $char)) {
$value = rand(0, 35);
}
$char[] = $value;
}
However, this is a probabilistic approach and may take a lot of time to finish depending on what the output of rand happens to be (it's going to be especially bad if the number of values you want is close to the number of all possible values).
Additionally, if the number of values you want to pick is largish (let's say more than 50 or so) then in_array can prove to be a bottleneck. In that case it should be faster to use array keys to check for uniqueness instead of values, since searching for the existence of a key is constant time instead of linear:
$char = array();
for ($i = 0; $i < 100; ++$i) {
$value = null;
// Try random numbers until you find one that does not already exist
while($value === null || array_key_exists($char, $value)) {
$value = rand(0, 1000);
}
$char[$value] = $value;
}
$char = array_values($char); // reindex keys to start from 0
To change any repeated value for a random one, you should loop through the array twice:
$cont= 0;
foreach($char as $c){
foreach($char as $d){
if($c == $d){
//updating the value
$char[$cont] = rand(0,35);
}
}
$cont++;
}
But what I don't know is if the random value can also be repeated. In that case it would not be so simple.
I've taken this code from the PHP Manual page for rand()
<?php
function uniqueRand($n, $min = 0, $max = null)
{
if($max === null)
$max = getrandmax();
$array = range($min, $max);
$return = array();
$keys = array_rand($array, $n);
foreach($keys as $key)
$return[] = $array[$key];
return $return;
}
?>
This function generates an array which has a size of $n and you can set the min and max values like in rand.
So you could make use of it like
uniqueRand(10, 0, 35);
Use array_count_values() first on the $char array.
Afterwards you can just loop all entries with more than 1 and randomize them. You have to keep checking until all counts are 1 tho. As even the random might remake a duplicate again.
I sugggest two option to make random array:
<?php
$questions = array(1, 2, 3, 4, 5, ..., 34, 35);
$questions = shuffle($questions);
?>
after that you choose the top 10 elements.
you can try this code to replace any repeated value.
for ($i = 0; $i < count($char); $i++) {
for ($n = 0; $n < count($char); $n++) {
if($char[$i] == $char[$n]){
$char[$i] = rand(0,35);
}
}
}
The function array_unique() obtains all unique values from an array, keyed by their first occurrence.
The function array_diff() allows to remove values from one array that are inside another array.
Depending on how you need to have (or not have) the result keyed or the order of keys preserved you need to do multiple steps. Generally it works as I outline in the following paragraphs (with PHP code-examples):
In an array you've got N elements of which Nu are unique.
$N = array(...);
$Nu = array_unique($N);
The number of random elements r you need then to replace the duplicates are the count of N minus the count of Nu. As the count of N is generally a useful value, I also assign it to nc:
$nc = count($N);
$r = $nc - count($Nu);
That makes r an integer ranging from 0 to count(N) - 1:
0 : no duplicate values / all values are unique
1 : one duplicate value / all but one value are unique
...
count(N) - 1 : all duplicate values / no unique value
So in case you you need zero random values ($r === 0) the input $N is the result. This boundary condition is the second most simple result (the first simple result is an input array with no members).
For all other cases you need r random unique values. In your question you write from 0 to 35. However this can not be the full story. Imagine your input array has got 36 duplicated values, each number in the range from 0 to 35 is duplicated once. Adding random numbers from the range 0 to 35 again to the array would create duplicates again - guaranteed.
Instead I've read your question that you are just looking for unique values that are not yet part of the input array.
So you not only you need r random values (Nr), but they also must not be part of N or Nu so far.
To achieve that you only need to create count(N) unique values, remove the unique values Nu from these to ensure nothing duplicates values in Nu. As this the theoretical maximum and not the exact number needed, that array is used to obtain the slice of exactly r elements from:
$Nr = array_slice(array_diff(range(0, $nc - 1), $Nu), 0, $r);
If you also want to have these new values to be added shuffled as range(0, $nc - 1) is ordered, you can do the following:
shuffle($Nr);
That should bring the randomness you seem to ask for in your question back into the answer.
That now leaves you with the unique parts of the original array $Nu and r new values in $Nr. Merging both these arrays will give you a result array which ignores key => value relations (the array is re-index):
array_merge($Nu, $Nr);
For example with an exemplary array(3, 4, 2, 1, 4, 0, 5, 0, 3, 5) for $N, the result this gives is:
Array
(
[0] => 3
[1] => 4
[2] => 2
[3] => 1
[4] => 0
[5] => 5
[6] => 7
[7] => 9
[8] => 6
[9] => 8
)
As you can see all the unique values (0-5) are at the beginning followed by the new values (6-9). Original keys are not preserved, e.g. the key of value 5 was 6 originally, now it is 5.
The relation or key => value are not retained because of array_merge(), it does re-index number keys. Also next to unique numbers in Nr keys also need to be unique in an array. So for every new number that is added to the unqique existing numbers, a key needs to be used that was a key of a duplicate number. To obtain all keys of duplicate numbers the set of keys in the original array is reduced by the set of keys of all for matches of the duplicate numbers (keys in the "unique array" $Nu):
$Kr = array_keys(array_diff_assoc($N, $Nu));
The existing result $Nr can now be keyed with with these keys. A function in PHP to set all keys for an array is to use the function array_combine():
$Nr = array_combine($Kr, $Nr);
This allows to obtain the result with key => value relations preserved by using the array union operator (+):
$Nu + $Nr;
For example with the $N from the last example, the result this gives is:
Array
(
[0] => 3
[1] => 4
[2] => 2
[3] => 1
[5] => 0
[6] => 5
[4] => 8
[7] => 6
[8] => 9
[9] => 7
)
As you can now see for the value 5 it's key 6 has been preserved as well as for the value 0 which had the key 5 in the original array and now as well in the output instead of the key 4 as in the previous example.
However as now the keys have been preserved for the first occurrences of the original values, the order is still changed: First all previously unique values and then all new values. However you might want to add the new values in place. To do that, you need to obtain the order of the original keys for the new values. That can be done by mapping the order by key and the using array_multisort() to sort based on that order.
Because this requires passing return values via parameters, this requires additional, temporary variables which I've chosen to introduce starting with the letter V:
// the original array defines the order of keys:
$orderMap = array_flip(array_keys($N));
// define the sort order for the result with keys preserved
$Vt = $Nu + $Nr;
$order = array();
foreach ($Vt as $key => $value) {
$order[] = $orderMap[$key];
}
Then the sorting is done (here with preserving keys):
// sort an array by the defined order, preserve keys
$Vk = array_keys($Vt);
array_multisort($order, $Vt, $Vk);
The result then is:
array_combine($Vk, $Vt);
Again with the example values from above:
Array
(
[0] => 3
[1] => 4
[2] => 2
[3] => 1
[4] => 7
[5] => 0
[6] => 5
[7] => 8
[8] => 6
[9] => 9
)
This example output shows nicely that the keys are ordered from 0 to 9 as they were are well in the input array. Compared with the previous output you can for example see that the first added value 7 (keyed 4) is at the 5th position - same as the value keyed 4 in the original array. The order of the keys have been obtained as well.
If that is the result you strive for you can short-cut the path to this step as well by iterating the original arrays keys and in case each of those keys is not the first value of any duplicate value, you can pop from the new values array instead:
$result = array();
foreach ($N as $key => $value) {
$result[$key] = array_key_exists($key, $Nu) ? $Nu[$key] : array_pop($Nr);
}
Again with the example array values the result (varies from previous because $Nr is shuffled:
Array
(
[0] => 3
[1] => 4
[2] => 2
[3] => 1
[4] => 7
[5] => 0
[6] => 5
[7] => 8
[8] => 9
[9] => 6
)
Which in the end might be the simplest way to answer your question. Hope this helps you answering the question. Keep the following in mind:
divide your problem:
you want to know if a value is unqiue or not - array_unique() helps you here.
you want to create X new unique numbers/values. array_diff() helps you here.
align the flow:
obtain unique numbers first.
obtain new numbers first.
use both to process the original array.
Like in this example:
// original array
$array = array(3, 4, 2, 1, 4, 0, 5, 0, 3, 5);
// obtain unique values (1.)
$unique = array_unique($array);
// obtain new unique values (2.)
$new = range(0, count($array) - 1);
$new = array_diff($new, $unique);
shuffle($new);
// process original array (3.)
foreach ($array as $key => &$value) {
if (array_key_exists($key, $unique)) {
continue;
}
$value = array_pop($new);
}
unset($value, $new);
// result in $array:
print_r($array);
Which then (exemplary because of shuffle($new)) outputs:
Array
(
[0] => 3
[1] => 4
[2] => 2
[3] => 1
[4] => 9
[5] => 0
[6] => 5
[7] => 8
[8] => 7
[9] => 6
)

array_intersect a variable amount of arrays

I am creating a faceted search, and I'm am trying to use array_intersect to compare the arrays and find the inputs that match.
The problem is that I will have a variable amount of arrays at anytime depending on what filters the user has selected:
$array_1, $array_2, $array_3 etc...
How do I create an array_intersect function that is dynamic in this sense?
This is what I've tried:
$next_array = 0;
for($i = 0; $i < $array_count; $i++) {
$next_array++;
if ($i == 0) {
$full_array = ${array_.$i};
} else {
if(!empty(${cvp_array.$next_array})) {
$full_array = array_intersect($full_array, ${cvp_array_.$next_array});
}
}
}
------------- EDIT -------------
I'll try to narrow down my goal a bit more:
If the user clicks three filters, this results in three arrays being created with each having individual results:
Array_1 ( [0] => 2, [1] => 4, [2] => 6 )
Array_2 ( [0] => 1, [1] => 4, [2] => 6 )
Array_3 ( [0] => 6, [1] => 7, [2] => 8 )
I need code that will find the number that is in ALL of the arrays. And if there is no common number then it would end as false or something. In the case above, I'd need it to retrieve 6. If it was only the first two arrays, it would return 4 and 6.
Try this:
$fullArray = array($array1, $array2, $array3...);
call_user_func_array('array_intersect', $fullArray);
One can use:
$intersect = array_intersect(...$fullArray);
First of all, turn those arrays into an array of arrays. Then you can use array_reduce combined with array_intersect to reduce a variable amount of arrays down to one.
You can turn those array to a single array named $total_array by using array_combine(),
then use array_intersect($full_array, $total_array). I hope this useful

Categories