Using preg_replace to add quotes to array - php

I have this array:
$array = '[[Smarties, 50g, 3, 1.99],
[M&Ms Peanut, 49g, 3, 1.99],
[Oreo Cookies, 300g, 1, 3.99],
[Pepsi, 355ml, 3, 1.29]]';
I need to use json_decode, so I need to find a way to surround the information inside in quotes like this:
[["Smarties", "50g", "3", "1.99"],
["M&Ms Peanut", "49g", "3", "1"."99"],
["Oreo Cookies", "300g", "1", "3.99"],
["Pepsi", "355ml", "3", "1.29"]]
I tried using preg_replace, and this is what I'm currently getting (close, but it's separating the prices into two and also separating two-word names into two.):
[["Smarties", "50g", "3", "1"."99"],
["M"&"Ms" "Peanut", "49g", "3", "1"."99"],
["Oreo" "Cookies", "300g", "1", "3"."99"],
["Pepsi", "355ml", "3", "1"."29"]]
I'm having a really hard time understanding preg_replace and I'm hoping someone might be able to help.
Is there a way to use the separating commas as guides to determine where to put the quotes?

For a somewhat crude, but context-aware regex one could use:
$str = preg_replace("~ [\[\],\s]*\K [^,\[\]]+ ~x", '"$0"', $str);
↑ ↑
skip ][, capture non-
+ space commas/brackets
Where the charclass before \K skips structural characters, and the second […] only finds anything but commas and brackets - which then is wrapped in quotes.

One not optimal, but working example:
$result = json_decode(strtr(strtr($yourString, array('['=>'["', ']'=>'"]', ', '=>'","', ']","['=>'],[')), array(']","[' => '],[', '["[' => '[[', ']"]' => ']]')), true);

Process this string, something like,
$sample = explode('],', $array);
foreach ($sample as &$v)
{
$v = array_map('trim', explode(',', trim($v, '[ ]')));
}
Now, array becomes,
array (
0 =>
array (
0 => 'Smarties',
1 => '50g',
2 => '3',
3 => '1.99',
),
1 =>
array (
0 => 'M&Ms Peanut',
1 => '49g',
2 => '3',
3 => '1.99',
),
2 =>
array (
0 => 'Oreo Cookies',
1 => '300g',
2 => '1',
3 => '3.99',
),
3 =>
array (
0 => 'Pepsi',
1 => '355ml',
2 => '3',
3 => '1.29',
),
)
Simply, json_encode() will give,
string '[["Smarties","50g","3","1.99"],["M&Ms Peanut","49g","3","1.99"],["Oreo Cookies","300g","1","3.99"],["Pepsi","355ml","3","1.29"]]' (length=128)

Related

merging parts (branches) of associative arrays

I seem to get stuck at a (at first glance) simple thing:
I have a nested assoc array i.e.
"stock" => [
123 => [
3 => 17,
5 => 5,
7 => 0
],
456 => [
3 => 1,
5 => 3,
7 => 7
]
]
These represent stocks of items (123 and 456) in warehouses (3, 5 and 7).
Now I want to update stock in one warehouse for one item i.e.
"stock" => [
123 => [
3 => 11
]
]
I have tried to approach this via array_merge (re-keys the array) and array_merge_recursive (strangely does the same while it shouldn't - are numeric keys the reason?) but to no avail. Also I found this interesting bit https://vancelucas.com/blog/php-array_merge-preserving-numeric-keys/ but that replaces the entire branch of the array (so I'm losing warehouses 5 and 7).
Does anyone have some clever idea about this?
This should be enough:
$newArray = array_replace_recursive($sourceArray, $newDataArray);
Fiddle here https://3v4l.org/qdejB
Here is your snippet,
foreach ($temp['stock'] as $key => &$value) {
foreach ($value as $key1 => $value1) {
// no need to check, it will add at respective key matching
$arr['stock'][$key][$key1] = $value1;
}
}
working demo.
Correct me if I'm wrong, but nothing seems to be able to stop you from:
$foo['stock'][123][3] = 11;

Count unique values in a column of an array

I have an array like this:
$arr = [
1 => ['A' => '1', 'C' => 'TEMU3076746'],
2 => ['A' => '2', 'C' => 'FCIU5412720'],
3 => ['A' => '3', 'C' => 'TEMU3076746'],
4 => ['A' => '4', 'C' => 'TEMU3076746'],
5 => ['A' => '5', 'C' => 'FCIU5412720']
];
My goal is to count the distinct values in the C column of the 2-dimensional array.
The total rows in the array is found like this: count($arr) (which is 5).
How can I count the number of rows which contain a unique value in the 'C' column?
If I removed the duplicate values in the C column, there would only be: TEMU3076746 and FCIU5412720
My desired output is therefore 2.
Hope this simplest one will be helpful. Here we are using array_column, array_unique and count.
Try this code snippet here
echo count(
array_unique(
array_column($data,"C")));
Result: 2
combine array_map, array_unique, count
$array = [ /* your array */ ];
$count = count(
array_unique(
array_map(function($element) {
return $element['C'];
}, $array))))
or use array_column as suggested by sahil gulati, array_map can do more stuff which probably isn't needed here.
I had a very similar need and I used a slightly different method.
I have several events where teams are participating and I need to know how many teams there are in each event. In other words, I don't need to only know how many distinct item "C" there are, but how many items TEMU3076746 and FCIU5412720 there are.
The code will then be as is
$nbCs = array_count_values ( array_column ( $array, 'C' ) );
$nbCs will issue an array of values = Array([TEMU3076746] => 3 [FCIU5412720] => 2)
See example in sandbox Sandbox code
$data=array();
$data=[
1 => [
'A' => '1'
'C' => 'TEMU3076746'
]
2 => [
'A' => '2'
'C' => 'FCIU5412720'
]
3 => [
'A' => '3'
'C' => 'TEMU3076746'
]
4 => [
'A' => '4'
'C' => 'TEMU3076746'
]
5 => [
'A' => '5'
'C' => 'FCIU5412720'
]
];
$total_value=count(
array_unique(
array_column($data,"C")));
echo $total_value;
Most concisely, use array_column()'s special ability to assign new first level keys using the targeted column's values. This provides the desired effect of uniqueness because arrays cannot contain duplicate keys on the same level.
Code: (Demo)
echo count(array_column($arr, 'C', 'C')); // 2
To be perfectly clear, array_column($arr, 'C', 'C') produces:
array (
'TEMU3076746' => 'TEMU3076746',
'FCIU5412720' => 'FCIU5412720',
)
This would also work with array_column($arr, null, 'C'), but that create a larger temporary array.
p.s. There is a fringe case that may concern researchers who are seeking unique float values. Assigning new associative keys using float values is inappropriate/error-prone because the keys will lose precision (become truncated to integers).
In that fringe case with floats, fallback to the less performant technique: count(array_unique(array_column($arr, 'B))) Demo

Php subarrays code adds extra values

This is the php code:
$slavesites = array(
'Category1' => array('Anchor1', 'http://www.test1.com'),
'Category2' => array('Anchor2', 'http://www.test2.com')
);
foreach($slavesites as $category => $slavesite){
echo $category;
foreach($slavesite as $anc => $url){
echo $anc.'<br>';
echo $url.'<br>';
}
}
The problem is when I run the code, i get a "0" and "1":
Category10 **--- WHERE DOES THE 0 COME FROM?**
Anchor1
1 **---- WHERE DOES THE 1 COME FROM?**
http://www.test1.com
Category20 --- WHERE DOES THE 0 COME FROM?
Anchor2
1 ---- WHERE DOES THE 1 COME FROM?
http://www.test2.com
Ty!:)
Hope you can help...
second foreach iterates over array without proper indices set. that way default indices (0,1,2,...) are used and hence the number in output.
e.g. actually your definition is like this:
$slavesites = array(
'Category1' => array(0 => 'Anchor1', 1 => 'http://www.test1.com'),
'Category2' => array(0 => 'Anchor2', 1 => 'http://www.test2.com')
);
you should use 'list' instead of 'foreach' in the inner loop:
list($anc, $url) = $slavesite;
If you want to loop through your array like that, you have to store the elements as key-value pairs:
$slavesites = array(
'Category1' => array('Anchor1' => 'http://www.test1.com'),
'Category2' => array('Anchor2' => 'http://www.test2.com')
);
The 0 and the 1 are shown because you don't have keys defined and it therefores uses numerical keys.

Php array rebuild

I got an array looking like this:
array("canv" => array(1 => "4", 2 => "6", 3 => "9", 4 => "7");
I need it to look like this:
array("canv" => array("4", "6", "9", "7");
so I can easly check if the value exist this way:
if(isset($result["canv"][$gid])) where $gid is a number from "4", "6", "9", "7".
How can it be done?
This will flip the values to become keys and vice versa:
$result["canv"] = array_flip($result["canv"]);
So instead of
array(1 => "4", 2 => "6", 3 => "9", 4 => "7")
you'll have
array("4" => 1, "6" => 2, "9" => 3, "7" => 4)
But then again think about building the original array in the desired way and only do this if you can't afford that.
It won't work because you are looking for array keys, while 4, 6, 9 and 7 are the values, but if you use array_search($gid, $result['canv']) you'll find the index of $gid or false if $gid's value is not in the list.
So this will work:
if(array_search($gid, $result['canv']) !== false){
//Do Stuff
}
Without any modification, with your existing array, you can check it as:
if (in_array($gid, $result["canv"])) {
// $gid is in the array
}
Logically, if canv is to be an array of those values, the values should be array members rather than the array keys which point to members. You are asking to use them as array keys. Unless you want them to behave as keys later on, whereby they will be used to point to array values, you should not change them now.
Then I don't think you want it to look like that.... You want it to look like this:
array(
"canv" => array(
4 => "value",
6 => "value",
9 => "value",
7 => "value"
)
)
You did not specify what values you want, but it may not matter. You can arrive at at that however you want, but if you wind up with an array with (4,6,9,7) in it, you can just do array_flip and it will exchange the keys with the values.

Merging multiple multidimensional arrays

I have a variable number of multidimensional arrays but all with the same 4 possible values for each item.
For example:
Array
(
[companyid] => 1
[employeeid] => 1
[role] => "Something"
[name] => "Something"
)
but every array may have a different ammount of items inside it.
I want to turn all the arrays into one single table with lots of rows. I tried array_merge() but I end up with a table with 8, 12, 16... columns instead of more rows.
So... any ideas?
Thanks
Didn't test it, but you could try the following:
$table = array();
$columns = array('companyid' => '', 'employeeid' => '', 'role' => '', 'name' => '');
foreach($array as $item) {
$table[] = array_merge($columns, $item);
}
This should work since the documentation about array_merge say:
If the input arrays have the same string keys, then the later value
for that key will overwrite the previous one.
So you either get the value of the current item or a default value that you can specify in the $columns array.
$array1=Array
(
"companyid" => 1,
"employeeid" => 4,
"role" => "Something",
"name" => "Something",
);
$array2=Array
(
"companyid" => array(2,2,2),
"employeeid" => 5,
"role" => "Something2",
"name" => "Something2"
);
$array3=Array
(
"companyid" => 3,
"employeeid" => 6,
"role" => "Something3",
"name" => "Something3"
);
//Using array_merge
$main_array["companyid"]=array_merge((array)$array1["companyid"],(array)$array2["companyid"],(array)$array3["companyid"]);
$main_array["employeeid"]=array_merge((array)$array1["employeeid"],(array)$array2["employeeid"],(array)$array3["employeeid"]);
for($i=0;$i<count($main_array["companyid"]);$i++)
echo $main_array["companyid"][$i] + "<br />";
for($i=0;$i<count($main_array["employeeid"]);$i++)
echo $main_array["employeeid"][$i] + "<br />";
I've tested the code above and seems right.
You coult also improve this code into a DRY function.

Categories