So, I have an array that, for unrelated reasons, has one imploded field in itself. Now, I'm interested in exploding the string in that field, and replacing that field with the results of the blast. I kinda-sorta have a working solution here, but it looks clunky, and I'm interested in something more efficient. Or at least aesthetically pleasing.
Example array:
$items = array(
'name' => 'shirt',
'kind' => 'blue|long|L',
'price' => 10,
'amount' => 5);
And the goal is to replace the 'kind' field with 'color', 'lenght', 'size' fields.
So far I've got:
$attribs = array('color', 'lenght', 'size'); // future indices
$temp = explode("|", $items['kind']); // exploding the field
foreach ($items as $key => $value) { // iterating through old array
if ($key == 'kind') {
foreach ($temp as $k => $v) { // iterating through exploded array
$new_items[$attribs[$k]] = $v; // assigning new array, exploded values
}
}
else $new_items[$key] = $value; // assigning new array, untouched values
}
This should (I'm writing by heart, don't have the access to my own code, and I can't verify the one I just wrote... so if there's any errors, I apologize) result in a new array, that looks something like this:
$new_items = array(
'name' => 'shirt',
'color' => 'blue',
'lenght' => 'long',
'size' => 'L',
'price' => 10,
'amount' => 5);
I could, for instance, just append those values to the $items array and unset($items['kind']), but that would throw the order out of whack, and I kinda need it for subsequent foreach loops.
So, is there an easier way to do it?
EDIT:
(Reply to Visage and Ignacio - since reply messes the code up)
If I call one in a foreach loop, it calls them in a specific order. If I just append, I mess with the order I need for a table display. I'd have to complicate the display code, which relies on a set way I get the initial data.
Currently, I display data with (or equivalent):
foreach($new_items as $v) echo "<td>$v</td>\n";
If I just append, I'd have to do something like:
echo "<td>$new_items['name']</td>\n";
foreach ($attribs as $v) echo "<td>$new_items[$v]</td>\n";
echo "<td>$new_items['price']</td>\n";
echo "<td>$new_items['amount']</td>\n";
Associative arrays generally should not depend on order. I would consider modifying the later code to just index the array directly and forgo the loop.
Try this:
$items = array( 'name' => 'shirt', 'kind' => 'blue|long|L', 'price' => 10, 'amount' => 5);
list($items['color'], $items['lenght'], $items['size'])=explode("|",$items['kind']);
unset $items['kind'];
I've not tested it but it should work.
Associative arrays do not have an order, so you can just unset the keys you no longer want and then simply assign the new values to new keys.
one way
$items = array(
'name' => 'shirt',
'kind' => 'blue|long|L',
'price' => 10,
'amount' => 5);
$attribs = array('color', 'lenght', 'size');
$temp = explode("|", $items['kind']);
$s = array_combine($attribs,$temp);
unset($items["kind"]);
print_r( array_merge( $items, $s) );
This should retain the ordering because it splits the keys and values into two numerically ordered arrays and combines them at the end. It isn't more efficient, but the code is easier to read.
$kind_keys = array('color', 'length', 'size');
$kind_values = explode("|", $items['kind']);
$keys = array_keys($items);
$values = array_values($items);
$index = array_search('kind', $keys);
// Put the new keys/values in:
array_splice($keys, $index, 1, $kind_keys);
array_splice($values, $index, 1, $kind_values);
// combine the result into a new array:
$result = array_combine($keys, $values));
Related
I need to check if the keys of an array match an array of keys, and if they don't match then they need to be created. While I managed to create the check I still need to return all keys that don't match in the in_array condition so that they can be added to the original array. How can I achieve this?
My current code:
$new_value = ['id','name','age'];
$keys = ['id','name','age','sex','height','weight'];
foreach($new_value as $new_value){
if(!in_array($new_value, $keys )){
$new_value["{$key}"] = '';
}
}
The desired result would be:
Array pre processing:
'id' => 1,
'name' => 'Ed',
'age' => 15,
Array post processing:
'id' => 1,
'name' => 'Ed',
'age' => 15,
'sex' => '',
'height' => '',
'weight' => '',
So, there are a couple of things here.
// When you are running through your foreach, you don't want to overwrite your
// array variable with the value, which is what is happening. Switch this to `new_values` (plural)
$new_values = ['id','name','age'];
$keys = ['id','name', 'age','sex','height','weight'];
// Since $keys is your desired structure, we want to loop through $key rather than $new_values, and add any missing keys to the $new_values
foreach($keys as $key){
// We want to check if $new_values has all the $keys (you were checking if $keys had all of $new_values, which it does already
if(!in_array($key, $new_values )){
// Since $key is already a string, we don't need to place it in quotes, just put the variable directly into the array as a new array item (because you are using an array of strings, the keys will be numerical)
$new_values[] = $key
}
}
If you are looking for a keyed array, so that you can get the value of $new_values['name'], then you will need to set your arrays up differently and do your checks differently. You can also use $keys to hold a default value.
// Set the keys for your array, instead of having an array of strings that is keyed numerically
$new_values = ['id' => 'user_id','name' => 'user name','age' => 'user age'];
$keys = ['id' => 'default_value','name' => 'default_value', 'age' => 'default_value','sex' => 'default_value','height' => 'default_value','weight' => 'default_value'];
// Here we'll get the key and value of each item in the $keys array
foreach($keys as $key => $default) {
// Check if the array key exists in new values and if not, set it to the predefined default value
if(!array_key_exists($key, $new_values) {
$new_values[$key] = $default;
}
}
EDIT
As per one of the comments on the answer, you could further simplify this with array_merge. If you want to throw an error or do something special on each field, you could use the loop. If you just want to fill in the blanks, it would work like:
// Set the keys for your array, instead of having an array of strings that is keyed numerically
$new_values = ['id' => 'user_id','name' => 'user name','age' => 'user age'];
$keys = ['id' => 'default_value','name' => 'default_value', 'age' => 'default_value','sex' => 'default_value','height' => 'default_value','weight' => 'default_value'];
// If you aren't going to be using the original $new_values array for anything, you can just overwrite it.
// As stated in the comment below, $new_values should be the second value, keys that are in both arrays will be overwritten by what's in the second array.
$new_values = array_merge($keys, $new_values);
// If you will be using the original $new_values array later in the code, you can set the output to a new variable
$filled_values = array_merge($keys, $new_values);
I'm not sure, but you can try next code:
<?php
$data = [
"id" => 1,
"name" => "Ed",
"age" => 15,
];
$keys = ["id", "name", "age", "sex", "height", "weight"];
$result = array_reduce(
$keys,
function ($data, $key) {
if (!isset($data[$key])) $data[$key] = '';
return $data;
},
$data
);
var_export($result);
PHP sandbox here
How to put these codes in a foreach loop?
$item1_details = array(
'id' => 'a1',
'price' => 18000,
'quantity' => 3,
'name' => "Apple"
);
$item2_details = array(
'id' => 'a2',
'price' => 20000,
'quantity' => 2,
'name' => "Orange"
);
Then the array above will be saved in a variable. It's an array. And, yes, I have no idea how to do a loop inside array. So please help me for this too.
$item_details = array ($item1_details, $item2_details);
Thus, I have to questions. First, how to create an array inside a foreach loop. Second, How to loop inside an array.
You don't put a loop inside an array, you push onto the array in a loop.
$item_details = array();
for ($i = 0; $i < 10; $i++) {
$item_details[] = $item1_details;
$item_details[] = $item2_details;
}
This will make an array with 10 alternating copies of $item1_details and $item2_details.
You mentioned a foreach loop, but that's for looping over an array that already exists. You didn't show any array to loop over, so I'm not sure how it applies in this case.
You can use array_values with array_merge
$f = array_merge(array_values($item1_details), array_values($item2_details));
Working example :- https://3v4l.org/fDM3N
The problem is the following:
I'm iterating over some data containing reservations for workstations with a foreach loop.
Inside this loop, I'm creating an associative array which looks like this:
$test = [
"id" => $id,
"name" => $forename." ".$surname,
"startDate" => date("Y-m-d", strtotime($startDate)-86400),
"endDate" => date("Y-m-d", strtotime($endDate)),
"color" => $color,
];
This array then shall be inserted into a numeric array (could be associative as well, but numeric would be easier).
I've tried array_merge, but it seems that it tries to insert the keys and their values into the destination array. This poses a problem, since the keys are always the same during each iteration. Therefore, during each iteration, the old keys and values are overwritten. Furthermore, I definitely NEED these arrays to stay arrays anyway, it would make life a lot easier for me later on.
I tried array_push but this doesnt seem to work, I get a NULL response.
Then I tried array_merge_recursively, and here the data is at least preserved, but it is split into numerical arrays indexed by the former associative key, referencing the data inside with numerical keys. This isnt the desired result either.
So how can I make it that I get this result:
$numericalArray = [[associativeArray1], [associativeArray2], [associativeArray3]]; //and so on
For further insight into my approach and the problems it causes, here's the function containing the foreach loop. The commented code contains the approaches I've already tried without success:
function createCalendarMarkupWithoutActiveDauerreservierung($connection, $allReservierungenData){
$calendarData = [];
//$calendarData = ["1"];
foreach($allReservierungenData as $reservierungData){
$color = setColorForDaterange($reservierungData['status']);
$username = retrieveReservierungUser($connection, $reservierungData["benutzer"]);
//$calendarData .= finalizeMarkupWithoutActiveDauerreservierung($reservierungData["id"], $username["vorname"], $username["name"], $reservierungData["anfang"], $reservierungData["ende"], $color);
$calendarDataSegment = finalizeMarkupWithoutActiveDauerreservierung($reservierungData["id"], $username["vorname"], $username["name"], $reservierungData["anfang"], $reservierungData["ende"], $color);
//$calendarData = array_merge($calendarData, ["2"]);
//$calendarData = array_merge($calendarData, $calendarDataSegment);
//$calendarData = array_push($calendarData, $calendarDataSegment);
//$calendarData = $calendarData + $calendarDataSegment;//array_merge($calendarData, $calendarDataSegment);
$calendarData = array_merge_recursive($calendarData, $calendarDataSegment);
}
return $calendarData;
}
Just append each array to your result:
<?php
$one = [
'id' => 'one',
'num' => 1
];
$result[] = $one;
$two = [
'id' => 'two',
'num' => 2
];
$result[] = $two;
var_export($result);
Output:
array (
0 =>
array (
'id' => 'one',
'num' => 1,
),
1 =>
array (
'id' => 'two',
'num' => 2,
),
)
If I understand you correctly, wouldn't you want something like this?
<?php
// example code
function createCalendarMarkupWithoutActiveDauerreservierung($connection, $allReservierungenData){
$calendarData = [];
foreach($allReservierungenData as $reservierungData){
$calendarDataSegment = finalizeMarkupWithoutActiveDauerreservierung($reservierungData["id"], $username["vorname"], $username["name"], $reservierungData["anfang"], $reservierungData["ende"], $color);
$calendarData = $calendarData[$reservierungData["id"]] = $calendarDataSegment);
}
return $calendarData;
}
So I have various arrays which do not always have the same key/value pairs in them. What I want to do is to be able to merge the arrays, but to add in empty key/value pairs if they don't already exist in that array, but do in others. It's hard to explain but this might explain it better:
$arrayOne = array('name' => 'rory', 'car' => 'opel');
$arrayTwo = array('name' => 'john', 'dog' => 'albert');
I need to somehow turn this into:
$finalArray = array(
array('name' => 'rory', 'car' => 'opel', 'dog' => ''),
array('name' => 'john', 'car' => '', 'dog' => 'albert')
);
I have been looking through PHP's documentation but can't find anything that will do this for me. Can anyone point me in the right direction? I don't even know an appropriate search term for what I want to achieve here, "array merge" isn't specific enough.
<?php
$arrayOne = array('name' => 'rory', 'car' => 'opel');
$arrayTwo = array('name' => 'john', 'dog' => 'albert');
$diff1=array_diff(array_flip($arrayOne), array_flip($arrayTwo));
$diff2=array_diff(array_flip($arrayTwo), array_flip($arrayOne));
//array_flip flips the key of array with value
//array_diff would return the values in the first array that are not present in any of the other arrays inside
foreach ($diff2 as $s) {
$arrayOne[$s]="";
}
foreach ($diff1 as $s) {
$arrayTwo[$s]="";
};
//set key that didn't exist in that array as ""
$finalArray[]=$arrayOne;
$finalArray[]=$arrayTwo;
//add the arrays to the final array
print_r($finalArray);
Here's what I would do:
Merge your separate arrays into one (into a temporary var) using array_merge
Get the unique keys of this new array using array_keys
For each separate array, loop through the new keys array and add an empty value for each key that is not in the array. Then push the separate array into a final array.
<?php
$arrayOne = array('name' => 'rory', 'car' => 'opel');
$arrayTwo = array('name' => 'john', 'dog' => 'albert');
$new = array_merge($arrayOne,$arrayTwo);
$new = array_keys($new);
$newarray = array();
foreach($new as $value){
$newarray[0][$value] = isset($arrayOne[$value]) ? $arrayOne[$value] : '' ;
$newarray[1][$value] = isset($arrayTwo[$value]) ? $arrayTwo[$value] : '' ;
}
echo "<pre>";print_r($newarray);
You can also use this short answer
$arrayOne = array('name' => 'rory', 'car' => 'opel');
$arrayTwo = array('name' => 'john', 'dog' => 'albert');
$defaults = array('name' => '','car' => '','dog' => '');
$arrayOne += $defaults;
$arrayTwo += $defaults;
$newarray = array($arrayOne,$arrayTwo);
echo "<pre>";print_r($newarray);
Basing on what Justin Powell outlined, I managed to come up with this code before the other two code examples were posted (thank you mamta & user6439245).
I also needed to take the keys containing numbers and sort them appropriately, otherwise my keys would've been indexed like employer_1, education_1, employer_2, education_2.
// get the initial form entries data
$entries = array(
array('name' => 'john', 'car' => 'fiat', 'employer_1' => 'tangerine', 'education_1' => 'hideaways', 'education_2' => 'extras'),
array('name' => 'rory', 'car' => 'opel', 'employer_1' => 'sagittarius', 'employer_2' => 'tangerine', 'employer_3' => 'thehideout', 'education_1' => 'knatchbull')
);
// create an empty array to populate with all field keys
$mergedKeys = array();
// push all field keys into the array
foreach($entries as $entry){
foreach($entry as $key => $value){
array_push($mergedKeys, $key);
}
}
// remove duplicate keys from the array
$uniqueMergedKeys = array_unique($mergedKeys);
// create a new array to populate with the field keys we need to sort - the ones with numbers in
$keysToSort = array();
// push the number-containing keys into the array
$i=0;
foreach($uniqueMergedKeys as $uniqueKey){
if(1 === preg_match('~[0-9]~', $uniqueKey)){
array_push($keysToSort, $uniqueKey);
}
$i++;
}
// remove the number containing keys from the unique keys array
$uniqueMergedKeys = array_diff($uniqueMergedKeys, $keysToSort);
// sort the keys that need sorting
sort($keysToSort);
// put the newly sorted keys back onto the original keys array
foreach($keysToSort as $key){
array_push($uniqueMergedKeys, $key);
}
$final = array();
$i = 0;
foreach($entries as $entry){
foreach($uniqueMergedKeys as $key){
//if($entries[$i][$key]){
if (array_key_exists($key, $entries[$i])) {
$final[$i][$key] = $entries[$i][$key];
} else {
$final[$i][$key] = '';
}
}
$i++;
}
echo '<pre>'; print_r($final); echo '</pre>';
Hi I'm trying to loop through a array and set a keys value. Very basic question.
The Code I tried is below.
http://pastebin.com/d3ddab156
<?php
$testArray = array("bob1" => array( 'name' => "bob1", 'setTest' => '2'));
foreach($testArray as $item)
{
$item['setTest'] = 'bob';
}
print_r($testArray);
I imagine I'm missing something stupid here and it is going to be a D'oh! moment for me. What is wrong with it?
Thanks.
You do:
$testArray = array("bob1" => array( 'name' => "bob1", 'setTest' => '2'));
foreach($testArray as $item)
{
$item['setTest'] = 'bob';
}
print_r($testArray);
$item is a copy. You change the copy, not the real array. Try this:
$testArray = array("bob1" => array( 'name' => "bob1", 'setTest' => '2'));
foreach($testArray as $key => $item)
{
$testArray[$key]['setTest'] = 'bob';
}
print_r($testArray);
Or, if you have a lot of data in the array and want to avoid creating a complete copy of each element over every iteration, simply iterate over each element as a reference. Then only a reference to that item is created i memory and you can directly manipulate the array element by using $item:
$testArray = array("bob1" => array( 'name' => "bob1", 'setTest' => '2'));
foreach($testArray as &$item)
{
$item['setTest'] = 'bob';
}
print_r($testArray);
NOTE: be sure to unset $item after the loop so you don't inadvertantly modify the array later by using that variable name.