This question already has answers here:
PHP Associative Array Duplicate Keys
(6 answers)
Closed 4 years ago.
I need to add the same keys to the array, but with different values,
foreach ($selections as $selection) {
$array += [$selection['option_id']=>$selection['product_id']];
}
// example output
$array = [30=>12,14=>10],
but really it should be
[30=>7,30=>12,14=>10];
When the key repeats, it merges.
You just can't.
But you can make the value of this key an array.
So you'll have
$array = [30=>[7,12],14=>10];
You can use any array functions on $array[30]
What you should do is to return the products ids as an array:
$array = array_reduce($selections, function ($carry, $selection) {
if (!isset($carry[$selection['option_id']])) {
$carry[$selection['option_id']] = [];
}
$carry[$selection['option_id']][] = $selection['product_id'];
return $carry;
}, []);
Now the result would be:
[30 => [7, 12], 14 => [10]];
Keys in array are, as the word itself says, keys to access the value they contain and each key must be unique, else you won't have a way to . If you could have two time or more the same value, how could you tell which will access one value and which one will access the other one? To solve your problem you have a way: generate a multidimensional array such that you can have multiple value stored "behind" a single key. E.g. [30 => [7,12], 14 => 10]
Based on your code you can just create a double loop with a nested foreach to navigate through all the value, something like:
foreach ($selections as $selection) {
if(!is_array($selection['product_id']) $array += [$selection['option_id']=>$selection['product_id']];
else {
foreach ($selection['product_id'] as $product) {
$array += [$selection['option_id']=> product];
}
}
}
Hey everyone I have a question about arrays and loops in PHP.
For a game I'm making, I need to write a function that generates a stack of crystal_id's based on a given size and ratio.
The ratio is the ratio between black crystals and different colored crystal (so a ratio of 0,25 (1:4) and a stack of 50 would yield a stack with 40 black crystals and 10 colored crystals).
I have all the math to calculate the amount of crystals per color and stuff figured out, but I can't figure out how to create an array with the right amount of colored crystals where each color is represented equally.
For reference, the array the code gets to choose from is a variable called $crystals_array, which is an array filled with integers where each integer represents a different colored crystal (e.g. [2,3,4,5,6]).
In the above case we have 5 different colored crystals and we needed a total of 10 colored crystals where each crystal is represented equally. So I need to create an array that looks a little something like this:
[2,2,3,3,4,4,5,5,6,6].
The code I have so far is this:
for($i = 0; $i <= count($amount_crystals_color) - 1; $i++)
{
$array = array_fill(0, $amount_crystals_per_color_stack, $crystals_array[$i]);
$i++;
}
Using the above example $amount_crystals_per_color_stack is equal to 2 and amount_crystals_color is equal to 5.
When executing this code it outputs an array: [2,2] which is how many 2's we need, but I can't figure out how to add the remaining crystals to this array.
Can anyone help me out?
Your code has several problems and i will address each of them individually.
Using the for loop to iterate over an array
You are using a for loop in your code, that has the following loop head:
for($i = 0; $i <= count($crystals_array) - 1; $i++)
The loop had consists of three parts, each separated by a semicolon (;).
The first part $i = 0 is the initialization part. Here you initialize a variable, that is later used as an iterator, which shall change in each loop iteration. You could name this the start point as well.
The second part $i <= count($crystals_array) - 1 is the condition part. A condition is formed, that shall express for how long the loop shall iterate. As long as the expression evaluates as true, the loop will run again. Therefore this condition is evaluated at the start of each iteration. As soon as the condition evaluates as false the loop will end. Therefore this part can be named endpoint as well.
The third part $i++ is the step size. This is executed at the end of each iteration and determines how the iterator (the variable you defined in the first part) shall change. $i++ is in this context equal to $i = $i + 1 and represents a step size of 1. Therefore the variable $i gets increased by 1 for each run of the loop.
This said, you can improve and fix your code regarding the for loop with two changes:
Save functions, that are executed in your condition part into an variable, if they return a constant result for each iteration. You use the count() function, which will then count your array again for each iteration of the for loop. By saving it in a variable $count = count($crystals_array); before the for loop and changing the condition to $i < $count, the function is only called once and your code gets faster.
Do not change the iterator variable $i outside of your loop header. This is really bad code style. You added the line $i++; to the end of your loop, but that is already done in the step size part of the for header. Because that is executed at the and of each iteration as well you increased the step size to two, meaning that you only run the for loop with $i = 0, $i = 2 and $i = 4 instead of for each element.
For your code the usage of the $i iterator is only to address the elements of the initial array. Even though you should understand the for loop for the future, you should use a foreach loop for this case instead. The following code would be equivalent to your for loop.
//This code still contains another major bug and is jsut a partial improvvement
foreach($crystals_array as $crystal) {
$array = array_fill(0, $amount_crystals_per_color_stack, $crystal);
}
As you can see, you neither need to worry about counting the initial array, nor in which index the current value is. Instead the variable $crystal will automatically contain the next element for each iteration.
Appending elements to an array
You used the following line to save the newly generated elements in your array:
$array = array_fill(0, $amount_crystals_per_color_stack, $crystal);
If you look closely, you use a standard assignment with $array = at the beginning of your line. This means, that (like with each variable assignment) the previous value of the variable gets overwritten by the new value provided from the right side of the assignment. What you do not want yet is to overwrite the array, but to append something to it.
This can be done by adding two squared brackets to the end of the variable name: $array[] = .... Now, if the variable $array is really an array, what ever value is on the right side of the assignment will be appended to the array, instead of overwriting it.
Managing result types the right way
The following line still contains a major problem:
$array[] = array_fill(0, $amount_crystals_per_color_stack, $crystal);
The result type of array_fill() is an array itself. By appending it to the previous array, you would get the following structure:
$array = [
[2, 2],
[3, 3],
[4, 4],
[5, 5],
[6, 6],
];
As you can see, the code did exactly what it should but not what you wanted. Each result (array) was appended to the array. The result is therefore an array or arrays (or a multidimensional array). What you want instead, is that the values of the result are appended to the existing array.
PHP offers a function for that, named array_merge(). This function takes all elements for one (or more) array(s) and appends them to the end of the first array, that was given to the function. You can use it as followed:
$newCrystals = array_fill(0, $amount_crystals_per_color_stack, $crystal);
$array = array_merge($array, $newCrystals);
As you can see the latter line contains a normal assignment again. ($array =) This is because array_merge() does not modify the first array given to it, but creates a new array with the merged fields. Therefore the new array contains all values from the old one and it is safe to overwrite the old one with it.
The complete code would therefore be:
$array = [];
foreach($crystals_array as $crystal) {
$newCrystals = array_fill(0, $amount_crystals_per_color_stack, $crystal);
$array = array_merge($array, $newCrystals);
}
As I understood the problem
$crystals_array = [2,3,4,5,6];
$amount_crystals_per_color_stack = 2;
$res = [];
foreach($crystals_array as $v) {
// repeat each item from array $amount_crystals_per_color_stack times
$res = array_merge($res, array_fill(0, $amount_crystals_per_color_stack, $v));
}
print_r($res); // [2,2,3,3,4,4,5,5,6,6]
You need to merge your array at each iteration of the loop (repl online) or you lose the result each time.
Like:
$array = array();
for($i = 0; $i < count($amount_crystals_color); $i++)
{
$array = array_merge($array, array_fill(0, $amount_crystals_per_color_stack, $crystals_array[$i]);
}
Also you don't need the $i++ in the loop, because it iterate twice otherwise, and you don't need count(..)-1 if the condition is < instead of <=.
You could use simple foreach() to achieve this-
$amount_crystals_per_color_stack = 2;
$array = [2,3,4,5,6];
$result = array();
foreach($array as $a){
for($i=1;$i<=$amount_crystals_per_color_stack;$i++){
array_push($result, $a);
}
}
print_r($result);
Hi I have been struggling with population of an array if you can help it will be much appreciated.
So I have these two arrays $start_range[] and $end_range[] which both contain
respective values and both arrays are of the same size. For example: $start_range[0] = 1000 and $end_range[0]=[2000]. Now I want to fill a new array with the range between those numbers and keep the respectiveness of the values so as in the example $new_array[0] = range($start_range[0],$end_range[0]).
In the moment I am using this code here
for ($i=0; $i<sizeof($start_range); $i++) {
$new_array[] = range($start_range[$i], $end_range[$i]);
}
But my problem is that it generates arrays with the same data because it loops through the size of the array. As if the size of the array was 4 then it will generate 4 new exact same arrays. I can't break out of the loop as it generates arrays only from the first columns of the two arrays.
Any solution?
Would this do?
$newArray = array();
foreach ($startArray as $key => $value) {
$newArray[$key] = range($startArray[$key], $endArray[$key]);
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Are PHP Associative Arrays ordered?
If I add items to associative array with different keys, does order of addition conserved? How can I access "previous" and "next" elements of given element?
Yes, php arrays have an implicit order. Use reset, next, prev and current - or just a foreach loop - to inspect it.
Yes, it does preserve the order. you can think of php arrays as ordered hash maps.
You can think of the elements as being ordered by "index creation time". For example
$a = array();
$a['x'] = 1;
$a['y'] = 1;
var_dump($a); // x, y
$a = array();
$a['x'] = 1;
$a['y'] = 1;
$a['x'] = 2;
var_dump($a); // still x, y even though we changed the value associated with the x index.
$a = array();
$a['x'] = 1;
$a['y'] = 1;
unset($a['x']);
$a['x'] = 1;
var_dump($a); // y, x now! we deleted the 'x' index, so its position was discarded, and then recreated
To summarize, if you're adding an entry where a key doesnt currently exist in the array, the position of the entry will be the end of the list. If you're updating an entry for an existing key, the position is unchanged.
foreach loops over arrays using the natural order demonstrated above. You can also use next() current() prev() reset() and friends, if you like, although they're rarely used since foreach was introduced into the language.
also, print_r() and var_dump() output their results using the natural array order too.
If you're familiar with java, LinkedHashMap is the most similar data structure.
$index = 0;
foreach ($sxml->entry as $entry) {
$array + variable index number here = array('title' => $title);
$index++;
}
I'm trying to change an array name depending on my index count. Is it possible to change variable name (ie. $array1, $array2 $array3 etc.) in the loop?
Edit:
After the loop has finished, I will generate a number number (depending on the count of $index) and then use this array... probably it's a stupid way of accomplishing what Im trying to do, but I don't have a better idea.
You might want to try this instead:
$index = 0;
$arrays = array();
foreach ($sxml->entry as $entry) {
$arrays[$index] = array('title' => $title);
$index++;
}
While it is technically possible to do what you are asking, using an array of arrays will probably work better from you.
This type of indexing is exactly what arrays are designed for, you have a lot of items and want to be able to refer to them by number.
Unless you have a very specific reason to use the name of the variable to represent it's number you will probably have a much simpler time using it's index in the outer array.
Yes you can user an associate array. Generating a string dynamically based on the iteration number and using that as a key in the array.
You can use variable variables. php.net
PHP supports Variable variables:
$num = 1;
$array_name = 'array' . $num;
$$array_name = array(1,2,3);
print_r($array1);
http://php.net/manual/en/language.variables.variable.php