I usually use Eloquent so transposing the data is much easier. However i'm struggling to this in vanilla PHP.
I have tried array_map(null, ...$array) however get an error due to it not being an array.
I have got the following keyed array:
[
'email' => [
"william.pool#gmail.com",
"martynleeball#gmail.com"
],
'lastName' => [
'Pool',
'Ball'
],
'firstName' => [
'William',
'Martyn'
],
'id' => [
'j8zwyk',
'1'
]
]
I need to convert this to the following format:
[
0 => [
'email' => "william.pool#gmail.com",
'lastName' => 'Pool',
'firstName' => 'William',
'id' => 'j8zwyk'
],
1 => [
'email' => "martynleeball#gmail.com",
'lastName' => 'Ball',
'firstName' => 'Martyn',
'id' => '1'
]
]
Create new array with length 2 and loop through origin array. In loop insert relevant item into new array.
So if your array has only 2 item per key use
$newArr = [];
foreach($arr as $key=>$item){
$newArr[0][$key] = $item[0];
$newArr[1][$key] = $item[1];
}
But if it has unknown item use
$newArr = [];
foreach($arr as $key=>$item){
foreach($item as $key2=>$item2)
$newArr[$key2][$key] = $item2;
}
Check result in demo
$newArray = [];
foreach ($array as $key => $value) {
for ($i = 0; $i < count($value); $i++) {
$newArray[$i][$key] = $value[$i];
}
}
Related
I have a a number of values/IDs that need to be translated to a single ID, what is the recommended method using PHP?
For example, I want IDs 38332, 84371, 37939, 1275 to all translate to ID 1234 and IDs222, 47391, 798 to all translate to ID 1235, etc. .
I'm thinking PHP has something built-in to handle this efficiently?
I'm thinking PHP has something built-in to handle this efficiently?
You can use the standard array as a map, quickly translating one ID to another:
$table[38332]; # int(1234)
depending on how you store your overall translation table, you can create a function that returns the translation from its input:
$table = $translation('I want IDs 38332, 84371, 37939, 1275 to all translate to ID 1234');
$result = $table[1275] ?? null; # int(1234)
Example:
$parseId = static fn(string $i) => (int)trim($i);
$translation = static fn(string $buffer): array
=> preg_match_all('~((?:\d+,\s*)+\d+)\s+to all translate to ID\s*(\d+)~', $buffer, $_, PREG_SET_ORDER)
? array_reduce($_, static fn (array $carry, array $item): array => [
$ids = array_map($parseId, explode(',', $item[1])),
$carry += array_fill_keys($ids, $parseId($item[2])),
$carry,][2], []) : [];
This is pretty easy to accomplish with PHP, here's one way you could do it:
Using this method, you populate the $map array, using the id you want to replace with as the key, and the value being an array of the keys you want to be replaced. It then calculates a simple key => value array based on this to make comparison a lot quicker.
Instead of creating a copy of the data, you could use foreach ($data as &$record)
$data = [
[
'id' => 1,
'foreign_id' => 38332,
'text' => 'a'
],
[
'id' => 2,
'foreign_id' => 84371,
'text' => 'b'
],
[
'id' => 3,
'foreign_id' => 37939,
'text' => 'c'
],
[
'id' => 4,
'foreign_id' => 1275,
'text' => 'd'
],
[
'id' => 5,
'foreign_id' => 222,
'text' => 'e'
],
[
'id' => 5,
'foreign_id' => 47391,
'text' => 'f'
],
[
'id' => 5,
'foreign_id' => 798,
'text' => 'g'
]
];
$map = [
123 => [
38332,
84371,
37939,
1275
],
1235 => [
222,
47391,
798
]
];
// Calculate a map to speed things up later
$map_calc = [];
foreach ($map as $destination_id => $ids) {
foreach ($ids as $id) {
$map_calc[$id] = $destination_id;
}
}
$new_data = [];
foreach ($data as $record) {
if (isset($map_calc[$record['foreign_id']]))
$record['foreign_id'] = $map_calc[$record['foreign_id']];
$new_data[] = $record;
}
var_dump($new_data);
I have a multidimensional array like this:
[
[
'id' => 1,
'name' => 'John',
'address' => 'Some address 1'
'city' => 'NY'
],
[
'id' => 2,
'name' => 'Jack',
'address' => 'Some address 2'
'city' => 'NY'
]
...
[ ... ]
]
How can I remove elements in all subarrays and only retain the id and name keys with their values?
Would this work?
$result = array_map(function($arr) {
return [
'id' => $arr['id'],
'name' => $arr['name']
];
}, $orig_array);
You want to retain the first two associative elements, so you can make array_slice() calls within array_map(). (Demo)
var_export(
array_map(fn($row) => array_slice($row, 0, 2), $array)
);
Or mapped called of array_intersect_key() against an establish whitelist array. (Demo)
$keep = ['id' => '', 'name' => ''];
var_export(
array_map(
fn($row) => array_intersect_key($row, $keep),
$array
)
)
Or, you could use array destructuring inside of a classic foreach() and make iterated compact() calls. (Demo)
$result = [];
foreach ($array as ['id' => $id, 'name' => $name]) {
$result[] = compact(['id', 'name']);
}
var_export($result);
If you want to edit the same array in place, you can simply iterate over them and unset them.
<?php
$preserve_keys = ['id','name'];
foreach($arr as &$data){
foreach($data as $key => $value){
if(!in_array($key,$preserve_keys)){
unset($data[$key]);
}
}
}
If you want it as a separate result, loop over and add it to the new array.
<?php
$new_result = [];
foreach($arr as $data){
$new_result[] = [
'id' => $data['id'],
'name' => $data['name']
];
}
print_r($new_result);
How would one do the following with laravel collections
We got this array : Let's assume we don't know the multi keys in advance
$input =[
['name' =>'John McClane','age'=>'40' ],
['name' =>'John McClane','age'=>'50' ],
['name' =>'Hans Gruber','age'=>'40' ],
['name' =>'Hans Gruber','age'=>'50' ],
['name' =>'Holly McClane','age'=>'20' ],
['name' =>'Holly McClane','age'=>'49' ],
];
$output =[
'name' => [
'John McClane',
'Hans Gruber',
'Holly McClane'
],
'age' =>[
'40',
'50',
'20',
'49'
]
];
Update : #Felippe Duarte added the PHP plain version on how one would do it.
$output =[];
foreach($input as $arr){
$keys = array_keys($arr);
foreach ($keys as $key) {
$output[$key] = array_unique(array_column($input, $key));
}
}
Just replacing array_unique(array_column($input, $key));
with $input->pluck($key)->toArray(); is not very interesting.
What I am wondering , is there a neat way to this entirely with a laravel collection in a single line?
Group by multidimensional keys, with unique values.
Cheers!
With plain PHP you can use array_column and array_unique:
$output = [
'name' => array_unique(array_column($input, 'name')),
'age' => array_unique(array_column($input, 'age')),
];
With collection you can use pluck and unique:
$output = [
'name' => $input->pluck('name')->unique(),
'age' => $input->pluck('age')->unique(),
];
If you don't know the keys, use array_keys or keys(), get the keys then repeat the above process:
$keys = array_keys($input); //$input->keys();
foreach ($keys as $key) {
$output[$key] = $input->pluck($key)->unique();
}
I have 2 arrays, I want match this arrays and get results with keys.
Can I search in first array with second array keys or match diffrent way?
$boardLists = [
[
'_id' => 'a1a1a1',
'name' => 'Board Name #1',
'code' => 'B1'
],
[
'_id' => 'b2b2b2',
'name' => 'Board Name #2',
'code' => 'B2
]
];
and
$boards = [
'a1a1a1',
'b2b2b2',
'c3c3c3'
];
My result with array_intersect:
array(1) { [0]=> string(6) "a1a1a1" }
My expected result if match 'a1a1a1':
[
'_id' => 'a1a1a1',
'name' => 'Board Name #1',
'code' => 'B1'
],
That I could understand you want to search in the first array according to what you have in the second array, so here is one example:
$boardLists = [
[
'_id' => 'a1a1a1',
'name' => 'Board Name #1',
'code' => 'B1'
],
[
'_id' => 'b2b2b2',
'name' => 'Board Name #2',
'code' => 'B2'
]
];
$boards = [
'a1a1a1',
'b2b2b2',
'c3c3c3'
];
$boardListIds = array_column($boardLists, '_id');
$results = [];
foreach ($boards as $board) {
$find_key = array_search($board, $boardListIds);
if($find_key !== false)
$results[] = $find_key;
}
#printing the results
foreach ($results as $result) {
print_r($boardLists[$result]);
}
There many ways to do it, this is just one. I hope it helps. :)
It would be more efficient to have the array index of your first array the _id. However with the way the array is setup currently you could do:
foreach($boards as $key1=>board){
foreach($boardLists as $key2=>$boardList){
if($boardList['_id']==$key1){
echo $key1 . PUP_EOL;
print_r($boardList);
}
}
}
Try this
$finalArray = array();
foreach($boardLists as $key=>$val):
if(in_array($val['_id'],$boards))
{
$finalArray[] = $val2;
}
endforeach;
The question is simple, I want to create the array below dynamically, but the code I got now only outputs the last row. Is there anybody who knows what is wrong with my dynamically array creation?
$workingArray = [];
$workingArray =
[
0 =>
[
'id' => 1,
'name' => 'Name1',
],
1 =>
[
'id' => 2,
'name' => 'Name2',
]
];
echo json_encode($workingArray);
/* My not working array */
$i = 0;
$code = $_POST['code'];
$dynamicArray = [];
foreach ($Optionsclass->get_options() as $key => $value)
{
if ($value['id'] == $code)
{
$dynamicArray =
[
$i =>
[
'id' => $key,
'name' => $value['options']
]
];
$i++;
}
}
echo json_encode($dynamicArray);
You dont need to have the $i stuff that is adding another level to your array that you dont want.
$code = $_POST['code'];
$dynamicArray = [];
foreach ($Optionsclass->get_options() as $key => $value)
{
if ($value['id'] == $code)
{
$dynamicArray[] = ['id' => $key, 'name' => $value['options'];
}
}
echo json_encode($dynamicArray);
You are creating a new dynamic array at each iteration:
$dynamicArray =
[
$i =>
[
'id' => $key,
'name' => $value['options']
]
];
Instead, declare $dynamicArray = []; above the foreach, and then use:
array_push($dynamicArray, [ 'id' => $key, 'name' => $value['options']);
inside the array.