I want to map form fields to database fields.
I have two arrays..
One array is the data and contains the form field id as the key and the form field value as the value.
$data = array("inputEmail"=>"someone#somewhere.com","inputName"=>"someone"... etc
I also have an array which i intended to use as a map. The keys of this array are the same as the form fields and the values are the database field names.
$map = array("inputEmail"=>"email", "inputName"=>"name"... etc
What i want to do is iterate over the data array and where the data key matches the map key assign a new key to the data array which is the value of the map array.
$newArray = array("email"=>"someone#somewhere.com", "name"=>"someone"...etc
My question is how? Ive tried so many different ways im now totally lost in it.
This is made quite nice with a foreach loop
foreach( $data as $origKey => $value ){
// New key that we will insert into $newArray with
$newKey = $map[$origKey];
$newArray[$newKey] = $value;
}
A more condensed approach (eliminating variable used for clarification)
foreach( $data as $origKey => $value ){
$newArray[$map[$origKey]] = $value;
}
If you want to replace keys of one array with values of the other the solution is array_combine
<?php
$a = array('green', 'red', 'yellow');
$b = array('avocado', 'apple', 'banana');
$c = array_combine($a, $b);
print_r($c);
?>
print_r output
Array
(
[green] => avocado
[red] => apple
[yellow] => banana
)
Related
Ok so I have two arrays, one is an input array full of data like :
$array1 = ["_token" => "62d46d4h6dfh841df8h", "sku62" => "3e", "name62" => "meh", "sku61" => "3e", "name61" => "mah", "sku64" => "3e", "name64" => "moh"]
The other holds simply id's: $array2 = [64, 74, 61]
edit for clarity: $array1 is a snippet of input from a post request i.e. $array1 = $request->all(); The numbers present within the keys of this array are unique Id's appended on form generation to distinguish between rows with multiple form elements.
Each row has an "update" checkbox also with an appended unique id. When ticked this id shows up in the request e.g. update64.
$array2 was populated by doing a foreach through the request, identifying the update string and isolating the id:
foreach ($array1 as $id => $value) {
$idInt = filter_var($id, FILTER_SANITIZE_NUMBER_INT);
$str = preg_replace('/[0-9]+/', '', $id);
if ($str === "update") {
array_push($array2, $idInt);
}
}
I want a solution that returns the elements from $array1 that have the appended ids found in $array2.
My own attempt looks like this:
$relevant_keys = function($key1, $key2) {
return ((preg_replace('/[0-9]+/', '', $key1) === $key2)) ? 1 : -1;
};
$filtered = array_intersect_ukey($array1, array_flip($array2), $relevant_keys);
However $filtered is returning empty and if I dd($key2) within the function it's not even returning an element from $array2, I get something from $array1 instead so this has left me confused.
Would appreciate any help.
Here's the solution to the exact problem you posted:
$filtered = [];
foreach ($array1 as $key => $value)
{
if ( ! preg_match('/(\d+)$/', $key, $matches)) continue;
if ( ! isset($matches[1]) || ! in_array($matches[1], $array2)) continue;
$filtered[$key] = $value;
}
But I'm not sure you're approaching this correctly. That input looks suspicious.
Are you sure there's no better way to format the request?
I have a few important insights to share based on your coding attempt.
array_intersect_ukey() should be the perfect function call for his task, but alas, it is not. I'll tell you why.
array_intersect_ukey() suffers in the same way as array_intersect_uassoc() and array_uintersect_uassoc() because the internal algorithm will stop looking for additional qualifying keys after it encounters its first one. I first came upon this reality here.
Also, the way that you've declared and used the custom function arguments ($key1 and $key2) indicates that you believe $key1 always relates to the first nominated array and $key2 always relates to the second nominated array. This is not true and I have seen many developers with this same false impression. The truth is that under the hood, the two parameters fed into the custom function may come from either array.
For the reasons in #1, I'll recommend that you shift your focus to array_filter(). By establishing a lookup array containing whitelisted keys and filtering on keys, you can swiftly filter your data. Inside the callback, I am using trim() to remove the letters before the id number at the end. This is just one way of isolating the whole number at the end of each key.
Code: (Demo)
$lookup = array_flip($array2);
var_export(
array_filter(
$array1,
fn($key) => isset($lookup[ltrim($key, 'a..z')]),
ARRAY_FILTER_USE_KEY
)
);
Output:
array (
'sku61' => '3e',
'name61' => 'mah',
'sku64' => '3e',
'name64' => 'moh',
)
I have an array that consists of an undetermined number of arrays, recursively (n levels deep). Each array might contain a name key. I want to create a unique list of those values.
Example
Suppose the array is:
$bigArray = array(
'name'=>'one',
'something'=>array(
'name'=>'two',
'subthing'=>array('name'=>'three')
),
'anotherthing'=>array('name'=>'one')
);
The expected result would be:
$uniques = array('one', 'two', 'three') // All the 'name' keys values and without duplicates.
Here's a fiddle of my attempt.
My approach was using array_walk_recursive passing a $uniques array as reference, and allowing the function to update that value:
$uniques = array();
function singleOut($item, $key, &$uniques) {
if ($key == 'name' && !in_array($itm,$uniques,true) )
$uniques[] = $item;
}
array_walk_recursive($bigArray, 'singleOut', $uniques);
However, it's not working for me.
You could use also array_unique on this one too. Example:
$uniques = array();
array_walk_recursive($bigArray, function($val, $key) use (&$uniques){
if($key == 'name') {
$uniques[] = $val;
}
});
$uniques = array_unique($uniques); // unique values
Your fiddle was nearly spot on - the problem was, that the user parameter is given by-reference only within same levels of recursion. You need to use indirection with a reference:
$bigArray = array(
'name'=>'one',
'something'=>array(
'name'=>'two',
'subthing'=>array('name'=>'three')
),
'anotherthing'=>array('name'=>'one')
);
function singleOut($item, $key, $indirect) {
$uniques=&$indirect[0];
if ($key == 'name' && !in_array($item,$uniques,true) ) $uniques[] = $item;
}
$uniques = array();
$indirect = array(&$uniques);
array_walk_recursive($bigArray, 'singleOut', $indirect);
print_r($uniques);
Edit:
Fiddle is here
To avoid doing an in_array() check inside of array_walk_recursive(), you can store name values as keys in the output array. This will effectively eliminate duplicates by overwriting previous identical keys. When array_walk_recursive() is finished, you can use array_keys() to move the data from keys to values.
Code: (Demo)
$bigArray=[
'name'=>'one',
'something'=>[
'name'=>'two',
'subthing'=>['name'=>'three']
],
'anotherthing'=>['name'=>'one']
];
array_walk_recursive($bigArray,function($v,$k)use(&$uniques){
if($k==='name')
$uniques[$v]='';
});
var_export(array_keys($uniques));
Output:
array (
0 => 'one',
1 => 'two',
2 => 'three',
)
Because array_unique() can be slow in some cases, using array_keys() should generally perform faster. That said, if micro-optimization is a concern then you should do benchmark testing using your actual data and your specific environment and select the best method for your project.
As I mentioned in a comment under Ghost's answer, it is a good habit to make === strict comparisons on keys in your multi-dimensional array because if you are looking for a string, but encounter a 0 key, then PHP's type juggling "feature" will provide unexpected results.
Here is a page where I discuss and demonstrate this behavior: Type juggling while making loose comparison yields unwanted result
I have produced an array of fruits stored somewhere. Say it looks like this
$myFruits = array("apples"=>1, "oranges"=>3, "bananas"=>5);
This array is then passed into a function that will return json-encoded data for an API.
First, I wanted to be able to return a list of all the types of fruits I have
{"fruits":["apples", "oranges", "bananas"]}
I used this to accomplish it
echo json_encode(array("scripts" => array_keys($scripts)));
Now, I would like each type of fruit to be contained in its own hash, as such
{"fruits":
[
{name: "apples"
},
{name: "oranges"
},
{name: "bananas"
]
}
This way I can add additional fields to each fruit object without breaking existing code that may be using previous versions of this API (eg: if I decided to add the fruit counts in there as well).
Seeing how I can just create a new array and assign my list of fruits to a key called "fruits", I tried to do the same for each inner hash:
$myFruits = array("apples"=>1, "oranges"=>3, "bananas"=>5);
$data = array();
foreach ($myFruits as $key => $value) {
// initialize an associative array for each fruit
$val = array();
array_push($val, array("name" => $key));
// add it to the list of fruits
array_push($data, $val);
}
// assign list of fruits to "fruits" key
$outData = array("fruits" => $data);
echo json_encode($outData);
But I get this instead
{"fruits":[[{"name":"apples"}],[{"name":"oranges"}],[{"name":"bananas"}]]}
There are extra square braces around each fruit hash, which I assume is because I'm using an array to store each key-value pair.
How would I get my desired output?
You're close to knowing what you're doing wrong. You're creating an array, and then just using it to add one item (another array) to it.
// initialize an associative array for each fruit
$val = array(); // this guy here is unnecessary!!
array_push($val, array("name" => $key));
// add it to the list of fruits
array_push($data, $val);
Instead, just push each individual array onto $data directly like this:
array_push($data, array("name" => $key));
DEMO
You are creating an extra level in your array, simply push a new array onto $data in each iteration:
foreach ($myFruits as $key => $value) {
$data[]=array("name" => $key, "count" => $value);
}
*edited as per your comment
I'm trying to systematically loop through 2 arrays, and match their values for some quick processing. Let me set up my specific situation:
Array 1
productID,
companyID,
name,
price
Array 2
companyID,
name,
rebate1,
rebate2
I want to loop through Array 1, and when the companyID matches an ID inside of Array 2, I will do some quick math based on the rebate1, rebate2 values for that companyID.
Right now I am looping through Array 1, and then on EACH item in Array 1 I loop through the entire Array 2 to see if the companyID exists. I know this can't be the fastest/cleanest solution...
EDIT
The key values for Array 1 look like:
$array1[0]['productID']
$array1[0]['companyID'] (etc...)
$array1[1]['productID']
$array1[1]['companyID'] (etc...)
The key values for Array 2 look like:
$array2[0]['companyID']
$array2[0]['rebate1'] (etc...)
$array2[1]['companyID']
$array2[1]['rebate1'] (etc...)
Use the companyId as key for Array 2, i.e., make sure that
$Array2[$Array1[$i]['companyID']]['companyID'] == $Array1[$i]['companyID']
This gives you constant time lookup of companies in Array 2 based on companyID and you can do your calculation with
$Array2[$Array1[$i]['companyID']]['rebate1']`
and
$Array2[$Array1[$i]['companyID']]['rebate2']`
Example:
foreach ($Array1 as $value) {
if (isset($Array2[$value['companyID']])) {
//TODO: use $Array2[$value['companyID']] for calculation
} else {
// TODO: handle case companyID not in $Array2
}
}
What approximate sizes do you expect for each of your arrays?
While as you say, your method isn't certainly the fastest (looks like 0(n²)), below 10'000 elements in each array I doubt you can see any significant speed difference.
If you have 150'000 in array1 and 200'000 in array2, that's a whole other story and you'll have to look for an algorithm that is rather 0(log n).
Edit:
As mentioned above, let's just make your array associative if you can:
Instead of:
Array2 = array(
0 => array(
'Company_id' => 'Hello',
'rebate_1' => '50%',
)
);
Make it:
Array2 = array(
'Hello' => array(
'rebate_1' => '50%',
)
);
And then use:
if (isset(array2[$company_id]))
{
// do your stuff
}
If you can't modify Array2's structure where it's coming from, you should transform it on the fly in your search function's scope, so that it looks like above, and then use the transformed array. Transforming Array2 into an associative one shouldn't take too long, for the number of elements you say you have.
The easiest way I can think of is to use the companyID as the key for Array 2:
$companies[$companyID]=array($name,$rebate1,$rebate2)
and then you just reference it directly looping Array 1
$products[$x]=array($productID,$companyID,$name,$price);
...
$newprice1=$products[$x][3]/$companies[$products[$x][1]][1];
$newprice2=$products[$x][3]/$companies[$products[$x][1]][2];
My answer is slightly different from the first one, mind the arrays...
You can create a new array indexed by the company id as follows:
$cid = array_map(function($a) {return $a['companyID'];}, $array2);
$new2 = array_combine($cid, $array2);
With that, you can loop through the first array and access the data:
foreach ($array1 as $key => $value){
$rebate1 = $new2[$value['companyID']]['rebate1'];
$rebate2 = $new2[$value['companyID']]['rebate2'];
}
I am using a form to create several arrays in a Session. Each time the form is submitted a new $_SESSION['item'][] is made containing each new array. The code for this:
$newitem = array (
'id' => $row_getshoppingcart['id'] ,
'icon' => $row_getimages['icon'],
'title' => $row_getimages['title'],
'medium' => $row_getshoppingcart['medium'],
'size' => $row_getshoppingcart['size'],
'price' => $row_getshoppingcart['price'],
'shipping' => $row_getshoppingcart['shipping']);
$_SESSION['item'][] = $newitem;
There could be any number of item arrays based on how many times the user submits the form. Any ideas how can I get the value of the array key that is being put in place of the [] in the session variable? I am trying to create a remove from cart option and cannot figure out how to reference that particular array in the session to unset it.
I am currently displaying the items as such:
<?php foreach ( $_SESSION['item'] AS $item )
echo $item['title'];
echo $item['icon'];
and so on...
Thank you in advance for your time. I really appreciate it.
foreach($_SESSION['item'] as $key => $value) will enable you to seperate the key and value, and ofcourse, to access the value current key has.
To extend this with an example, consider following code:
<?php
$exArray = array("foo"=>"bar", "foo2"=>"bar2);
foreach($exArray as $arrKey => $arrValue):
echo "The key ".$arrKey." has the value of ".$arrValue."<br />\n";
endforeach;
?>
will output:
The key foo has the value of bar.
The key foo2 has the value of bar2.
However, in the same way, if the $arrValue variable is known to hold an array, it will keep it's content. To loop through that second array, you will need to loop it through another foreach statement.
Just specify an index name in your foreach
foreach ($_SESSION['item'] as $idx => $item) {
var_dump($item);
var_dump($_SESSION['item'][$idx]);
}
The var_dumps will be the same.
$var = array_keys($arr);
$count = count($var);
$lastKey = $var[$count - 1];
That work for you?