PHP Unify duplicate array - php

in my PHP code I have many array like this:
0 = ['attr_id':1,'name':'qty','value':'100'];
1 = ['attr_id':1,'name':'qty','value':'200'];
2 = ['attr_id':1,'name':'qty','value':'500'];
3 = ['attr_id':2,'name':'price','value':'10$'];
I want merge this array like this:
0 = ['attr_id':1,'name':'qty','value':['100','200','500']];
1 = ['attr_id':1,'name':'price','value':'10$'];
can you guys help me please?
thanks

This should be simpler. Build the result using the attr_id as the index and append the value:
foreach($array as $values) {
$result[$values['attr_id']]['value'][] = $values['value'];
$result[$values['attr_id']] = $result[$values['attr_id']] + $values;
}
If you need to reindex, just use array_values() on the $result.

This is one method where you loop through an array_column array of the id's and use key to insert values from values array.
$value = array_column($arr, 'value');
$id = array_column($arr, 'attr_id');
$res =[];
Foreach($id as $key => $i){
If(!isset($res[$i])) $res[$i] = ['attr_id' => $i, 'name'=>'qty', 'value' => []];
$res[$i]['value'][] = $value[$key];
}
Var_dump($res);
https://3v4l.org/VXI5E
As you see I use the id as key to keep track of the result array.
If you want to clear this, meaning reset the counting from 0, use array_values.
$res = array_values($res);
Edit: also the 10$ is inside an array in my answer, this makes it easier to use the array later in my opinion.
If you must save it as an string I can fix it, but it will probably be harder to use the array later with a mixed item.

Related

Looking for an element in an array in PHP

I don't know if I'm managing this array in the best way.
The array I have is this:
$bass = $_POST['bass'];
$selected_scale = $_POST['scale'];
$major_scales = array
(
array("C","D","E","F","G","A","B","C","D","E","F","G","A","B",),
array("C#","D#","E#","F#","G#","A#","B#","C#","D#","E#","F#","G#","A#","B#",),
array("Db","Eb","F","Gb","Ab","Bb","C","Db","Eb","F","Gb","Ab","Bb","C",),
array("D","E","F#","G","A","B","C#","D","E","F#","G","A","B","C#"),
array("D#","E#","F##","G#","A#","B#","C##","D#","E#","F##","G#","A#","B#","C##"),
array("Eb","F","G","Ab","Bb","C","D","Eb","F","G","Ab","Bb","C","D"),
array("E","F#","G#","A","B","C#","D#","E","F#","G#","A","B","C#","D#"),
array("E#","F##","G##","A#","B#","C##","D##","E#","F##","G##","A#","B#","C##","D##"),
array("Fb","Gb","Ab","Bbb","Cb","Db","Eb","Fb","Gb","Ab","Bbb","Cb","Db","Eb"),
array("F","G","A","Bb","C","D","E","F","G","A","Bb","C","D","E"),
array("F#","G#","A#","B","C#","D#","E#","F#","G#","A#","B","C#","D#","E#"),
array("Gb","Ab","Bb","Cb","Db","Eb","F","Gb","Ab","Bb","Cb","Db","Eb","F"),
array("G","A","B","C","D","E","F#","G","A","B","C","D","E","F#"),
array("G#","A#","B#","C#","D#","E#","F##","G#","A#","B#","C#","D#","E#","F##"),
array("Ab","Bb","C","Db","Eb","F","G","Ab","Bb","C","Db","Eb","F","G"),
array("A","B","C#","D","E","F#","G#","A","B","C#","D","E","F#","G#"),
array("A#","B#","C##","D#","E#","F##","G##","A#","B#","C##","D#","E#","F##","G##"),
array("Bb","C","D","Eb","F","G","A","Bb","C","D","Eb","F","G","A"),
array("B","C#","D#","E","F#","G#","A#","B","C#","D#","E","F#","G#","A#"),
array("B#","C##","D##","E#","F##","G##","A##","B#","C##","D##","E#","F##","G##","A##"),
array("Cb","Db","Eb","Fb","Gb","Ab","Bb","Cb","Db","Eb","Fb","Gb","Ab","Bb")
);
$bass is a string, like the one inside the arrays. The $selected_scale is just a number.
What I'm trying to do is to find the $bass in one of those array in the position of $selected_scale. Basically, $bass = $major_scales[$selected_scale]. Therefore I want to create a loop in order to get the elements after that.
But I don't know how to manage in this case the situation. I've looked everything in internet and try various solutions without success. I'd like to know how can I do it. Thanks
Try to use next loop:
// if value exists in mentioned index
if (in_array($bass,$major_scales[$selected_scale])){
// index of that value in that array
$tmp_ind = array_search($bass,$major_scales[$selected_scale]);
// length of the array
$len = count($major_scales[$selected_scale]);
// store values after this value
$res = [];
for ($i=$tmp_ind;$i<$len;$i++){
$res[$i] = $major_scales[$selected_scale][$i];
}
}
print_r($res);
Demo1
If you need to find value by index $selected_scale in one of these arrays and also store values after this position:
foreach($major_scales as $ar){
if ($ar[$selected_scale] == $bass){
// length of the array
$len = count($ar);
// store values after this value
$res = [];
for ($i=$selected_scale;$i<$len;$i++){
$res[$i] = $ar[$i];
}
}
}
print_r($res);
Demo2

How to make key value by explode and arrange matching key values into one key?

I am recently facing a practical problem.I am working with ajax form submission and there has been some checkboxes.I need all checkboxes with same name as key value pair.Suppose there is 4 checkboxes having name attribute =checks so i want something like $arr['checks'] = array(value1, value2, ...)
So i am getting my ajax $_POST code as suppose like: name=alex&checks=code1&checks=code2&checks=code3
I am using below code to make into an array
public function smdv_process_option_data(){
$dataarray = array();
$newdataarray = array();
$new = array();
$notices = array();
$data = $_POST['options']; // data received by ajax
$dataarray = explode('&', $data);
foreach ($dataarray as $key => $value) {
$i = explode('=', $value);
$j = 1;
if(array_key_exists($i[0], $newdataarray)){
if( !is_array($newdataarray[$i[0]]) ){
array_push($new, $newdataarray[$i[0]]);
}else{
array_push($new, $i[1]);
}
$newdataarray[$i[0]] = $new;
}else{
$newdataarray[$i[0]] = $i[1];
}
}
die($newdataarray);
}
Here i want $newdataarray as like below
array(
'name' => 'alex',
'checks => array(code1, code2, code3),
)
But any how I am missing 2nd value from checks key array.
As I see it you only need to do two explode syntaxes.
The first on is to get the name and here I explode on & and then on name= in order to isolate the name in the string.
The checks is an explode of &checks= if you omit the first item with array_slice.
$str = 'name=alex&checks=code1&checks=code2&checks=code3';
$name = explode("name=", explode("&", $str)[0])[1];
// alex
$checks = array_slice(explode("&checks=", $str), 1);
// ["code1","code2","code3"]
https://3v4l.org/TefuG
So i am getting my ajax $_POST code as suppose like: name=alex&checks=code1&checks=code2&checks=code3
Use parse_str instead.
https://php.net/manual/en/function.parse-str.php
parse_str ( string $encoded_string [, array &$result ] ) : void
Parses encoded_string as if it were the query string passed via a URL and sets variables in the current scope (or in the array if result is provided).
$s = 'name=alex&checks=code1&checks=code2&checks=code3';
parse_str($s, $r);
print_r($r);
Output
Array
(
[name] => alex
[checks] => code3
)
You may think this is wrong because there is only one checks but technically the string is incorrect.
Sandbox
You shouldn't have to post process this data if it's sent correctly, as that is not included in the question, I can only make assumptions about it's origin.
If your manually creating it, I would suggest using serialize() on the form element for the data for AJAX. Post processing this is just a band-aid and adds unnecessary complexity.
If it's from a source outside your control, you'll have to parse it manually (as you attempted).
For example the correct way that string is encoded is this:
name=alex&checks[]=code1&checks[]=code2&checks[]=code3
Which when used with the above code produces the desired output.
Array
(
[name] => alex
[checks] => Array
(
[0] => code1
[1] => code2
[2] => code3
)
)
So is the problem here, or in the way it's constructed...
UPDATE
I felt obligated to give you the manual parsing option:
$str = 'name=alex&checks=code1&checks=code2&checks=code3';
$res = [];
foreach(explode('&',$str) as $value){
//PHP 7 array destructuring
[$key,$value] = explode('=', $value);
//PHP 5.x list()
//list($key,$value) = explode('=', $value);
if(isset($res[$key])){
if(!is_array($res[$key])){
//convert single values to array
$res[$key] = [$res[$key]];
}
$res[$key][] = $value;
}else{
$res[$key] = $value;
}
}
print_r($res);
Sandbox
The above code is not specific to your keys, which is a good thing. And should handle any string formatted this way. If you do have the proper array format mixed in with this format you can add a bit of additional code to handle that, but it can become quite a challenge to handle all the use cases of key[] For example these are all valid:
key[]=value&key[]=value //[key => [value,value]]
key[foo]=value&key[bar]=value //[key => [foo=>value,bar=>value]]
key[foo][]=value&key[bar][]=value&key[bar][]=value //[key => [foo=>[value]], [bar=>[value,value]]]
As you can see that can get out of hand real quick, so I hesitate to try to accommodate that if you don't need it.
Cheers!

Storing array within an array using PHP

foreach ($topicarray as $key=>$value){
$files = mysql_query("mysqlquery");
while($file = mysql_fetch_array($files)){ extract($file);
$topicarray[$value] = array( array($id=>$title)
);
}
}
The first foreach loop is providing me with an array of unique values which forms a 1-dimensional array.
The while loop is intended to store another array of values inside the 1-dimensional array.
When the while loop returns to the beginning, it is overwriting it. So I only ever get the last returned set of values in the array.
My array ends up being a two dimensional array with only one value in each of the inner arrays.
Feels like I'm missing something very basic here - like a function or syntax which prevents the array from overwriting itself but instead, adds to the array.
Any ideas?
Step 1. Replace $topicarray[$value] with $topicarray[$value][]
Step 2. ???
Step 3. Profit
Make $topicarray[$value] an array of rows, instead of one row. Also, don't use extract here.
foreach ($topicarray as $key => $value) {
$rows = array();
$files = mysql_query("mysqlquery");
while($file = mysql_fetch_array($files)) {
$rows[] = array($file['id'] => $file['title']);
}
$topicarray[$value] = $rows;
}
Also, you should switch to PDO or MySQLi.

Change the array KEY to a value from sub array

This is the set of result from my database
print_r($plan);
Array
(
[0] => Array
(
[id] => 2
[subscr_unit] => D
[subscr_period] =>
[subscr_fee] =>
)
[1] => Array
(
[id] => 3
[subscr_unit] => M,Y
[subscr_period] => 1,1
[subscr_fee] => 90,1000
)
[2] => Array
(
[id] => 32
[subscr_unit] => M,Y
[subscr_period] => 1,1
[subscr_fee] => 150,1500
)
)
How can I change the $plan[0] to $plan[value_of_id]
Thank You.
This won't do it in-place, but:
$new_plan = array();
foreach ($plan as $item)
{
$new_plan[$item['id']] = $item;
}
This may be a bit late but I've been looking for a solution to the same problem. But since all of the other answers involve loops and are too complicated imho, I've been trying some stuff myself.
The outcome
$items = array_combine(array_column($items, 'id'), $items);
It's as simple as that.
You could also use array_reduce which is generally used for, well, reducing an array. That said it can be used to achieve an array format like you want by simple returning the same items as in the input array but with the required keys.
// Note: Uses anonymous function syntax only available as of PHP 5.3.0
// Could use create_function() or callback to a named function
$plan = array_reduce($plan, function($reduced, $current) {
$reduced[$current['id']] = $current;
return $reduced;
});
Note however, if the paragraph above did not make it clear, this approach is overkill for your individual requirements as outlined in the question. It might prove useful however to readers looking to do a little more with the array than simply changing the keys.
Seeing the code you used to assemble $plan would be helpful, but I'm going assume it was something like this
while ($line = $RES->fetch_assoc()) {
$plan[] = $line;
}
You can simply assign an explicit value while pulling the data from your database, like this:
while ($line = $RES->fetch_assoc()) {
$plan[$line['id']] = $line;
}
This is assuming $RES is the result set from your database query.
In my opinion, there is no simpler or more expressive technique than array_column() with a null second parameter. The null parameter informs the function to retain all elements in each subarray, the new 1st level keys are derived from the column nominated in the third parameter of array_column().
Code: (Demo)
$plan = array_column($plan, null, 'id');
Note: this technique is also commonly used to ensure that all subarrays contain a unique value within the parent array. This occurs because arrays may not contain duplicate keys on the same level. Consequently, if a duplicate value occurs while using array_column(), then previous subarrays will be overwritten by each subsequent occurrence of the same value to be used as the new key.
Demonstration of "data loss" due to new key collision.
$plans = array();
foreach($plan as $item)
{
$plans[$item['id']] = $item;
}
$plans contains the associative array.
This is just a simple solution.
$newplan = array();
foreach($plan as $value) {
$id = $value["id"];
unset($value["id"]);
$newplan[$id] = $value;
}

Make 1d Array from 1st member of each value in 2d Array | PHP

How can you do this? My code seen here doesn't work
for($i=0;i<count($cond);$i++){
$cond[$i] = $cond[$i][0];
}
It can be as simple as this:
$array = array_map('reset', $array);
There could be problems if the source array isn't numerically index. Try this instead:
$destinationArray = array();
for ($sourceArray as $key=>$value) {
$destinationArray[] = $value[0]; //you may want to use a different index than '0'
}
// Make sure you have your first array initialised here!
$array2 = array();
foreach ($array AS $item)
{
$array2[] = $item[0];
}
Assuming you want to have the same variable name afterwards, you can re-assign the new array back to the old one.
$array = $array2;
unset($array2); // Not needed, but helps with keeping memory down
Also, you might be able to, dependant on what is in the array, do something like.
$array = array_merge(array_values($array));
As previously stated, your code will not work properly in various situation.
Try to initialize your array with this values:
$cond = array(5=>array('4','3'),9=>array('3','4'));
A solution, to me better readable also is the following code:
//explain what to do to every single line of the 2d array
function reduceRowToFirstItem($x) { return $x[0]; }
// apply the trasnformation to the array
$a=array_map('reduceRowTofirstItem',$cond);
You can read the reference for array map for a thorough explanation.
You can opt also for a slight variation using array_walk (it operate on the array "in place"). Note that the function doesn't return a value and that his parameter is passed by reference.
function reduceToFirstItem(&$x) { $x=$x[0]; }
array_walk($cond, 'reduceToFirstItem');
That should work. Why does it not work? what error message do you get?
This is the code I would use:
$inArr;//This is the 2D array
$outArr = array();
for($i=0;$i<count($inArr);$i++){
$outArr[$i] = $inArr[$i][0];
}

Categories