This question already has answers here:
Get first value of an array [duplicate]
(5 answers)
PHP: How to access the first element of an array returned by a static function [duplicate]
(2 answers)
Closed 2 years ago.
Not quite sure how to word this correctly, but I am looking for some help to to move/shift array keys so that the top level array doesn't contain another array with only one item. Basically from this:
[0] => Array
(
[0] => Array
(
[_id] => 3
[title] => Award winning wedding venue
[subtitle] => Creating a website to reflect the prestige of the brand
)
)
[1] => Array
(
[0] => Array
(
[_id] => 5
[title] => Bringing storytelling to life
[subtitle] => Bringing storytelling to life
)
)
to be like this:
[0] => Array
(
[_id] => 3
[title] => Award winning wedding venue
[subtitle] => Creating a website to reflect the prestige of the brand
)
[1] => Array
(
[_id] => 5
[title] => Bringing storytelling to life
[subtitle] => Bringing storytelling to life
)
Almost just shifting the array key up one.
The original array is created using the following:
// Start with manual relation otherwise default to next/prev
foreach ($item['related'] as $id) {
$related[] = perch_collection('Projects', [
'filter' => [
[
'filter' => '_id',
'match' => 'eq',
'value' => $id,
],
// Item is enabled
[
'filter' => 'status',
'match' => 'eq',
'value' => 'enabled',
],
],
'skip-template' => true,
], true);
}
It would be best if you modify the creation of your array instead of changing it afterwards.
// Start with manual relation otherwise default to next/prev
foreach ($item['related'] as $id) {
$related[] = perch_collection('Projects', [
'filter' => [
[
'filter' => '_id',
'match' => 'eq',
'value' => $id,
],
// Item is enabled
[
'filter' => 'status',
'match' => 'eq',
'value' => 'enabled',
],
],
'skip-template' => true,
], true)[0];
}
Note the [0] at the end of the perch_collection() function call. This is essentially the same as the second part of my answer, it just occurs earlier.
With that said, if you still want to change it after the original array is made, you could just use a simple foreach loop with a reference to the original array.
foreach($array as &$arr) {
$arr = $arr[0];
}
Using & in front of $arr is a reference. This means the loop will alter the original array, so it prevents the overhead of a temporary array.
mickmackusa let me know about another solution using array_column(), which avoids the loop completely.
$array = array_column($array, 0);
The best way to fix this problem would be at the source. This looks like a Dataset received from a database, so instead of trying to manipulate the array after you received it, you could also try to generate it in the correct format. Most DALs have methods to manipulate the return type of the resultset.
However, if that is not possible and you always only have a single element nested, this loop should do the trick.
for($i = 0; $i <= count($array); $i++) {
$shifted[$i] = $array[$i][0];
}
Related
Hopefully someone can help me :)
I have two arrays of distributor Products Info from separate datasources but with same structure. They are held in code as variables $distro1Products and $distro2Products.
Distro1:
[MZ-V7S500BW] => Array
(
[wooCode] => 13220
[price] => 74.00
[quantity] => 25
)
[...] => Array (.......)
MZ-V7S500BW - distro product code
Distro2:
[1256421] => Array
(
[wooCode] => 13220
[price] => 82.84
[quantity] => 50
)
[...] => Array (.......)
1256421- distro product code
What I want to do is to generate new array from both array results, something like this
[13220] => Array
(
[price] => 74.00
[quantity] => 25
)
I don't know if I can ask help with logic - script should pick cheapier entry (in this case - from Distro1) but it also must check if product is in stock (quantity > 0) and if both entries are out of stock, just return 0.
What I really really need right now is a way to generate new multidimensional array from existing two multidimensional arrays, also I have plans of integrating third distro, so expandability of code would be super nice :)
Thanks in advance! ♥
Is this working :
$distro1Products = [
'MZ-V7S500BW' => [
'wooCode' => 13220,
'price' => 74.00,
'quantity' => 25
]
];
$distro2Products = [
13220 => [
'price' => 74.00,
'quantity' => 25
]
];
$fusion = array_merge(...array_map(function($code, $tab) use($distro2Products) {
$wooCode = $tab['wooCode'];
return [$wooCode => $distro2Products[$wooCode]];
}, array_keys($distro1Products), $distro1Products));
?
The goal is to find how to have a link between 'wooCode' value from first array and key from second array. When you got association, you can build your array.
This question already has answers here:
PHP add elements to multidimensional array with array_push
(4 answers)
Closed 2 years ago.
I'm already getting below array results as follows. All I wanted is to add more entries in it.
How do I do that?
Array
(
[result] => Array
(
[0] => Array
(
[number] => AAA1222
[short_description] => User unable to print
[state] => Closed
)
[1] => Array
(
[number] => AAA1223
[short_description] => Share drive not accessible
[state] => Closed
)
[2] => Array
(
[number] => AAA1224
[short_description] => Network is down
[state] => Closed
)
)
)
If I wanted to add more entries to the array like
[number] => AAA1225
[short_description] => Cable replacement on workstation 12
[state] => Closed
How do I accomplish that.
Thanks!!
You can try with array_push() function too.
Your existence array:
$myArr['result'] = [........]
New array values
$data['number'] = 'AAA1224';
$data['short_description'] = 'Network is down';
$data['state'] = 'Closed';
Push new array into existance array:
array_push($myArr['result'],$data);
Considering you are storing above array in a variable named as $arr.
$arr = [ ... ]; // contains your existing data.
// To add new data
$arrNewData = [
'number' => 'AAA1225',
'short_description' => 'Cable replacement on workstation 12',
'state' => 'Closed'
];
// Push data to existing array.
$arr['result'][] = $arrNewData;
You can add another array data to your existing array
Keep your existing data into a variable $data.
$data = [ ... ]; // here you have result index and array data
Then add new result item as an array.
$data['result'][] = [
'number' => 'AAA1225',
'short_description' => 'Cable replacement on workstation 12',
'state' => 'Closed'
];
This question already has answers here:
Filter/Remove rows where column value is found more than once in a multidimensional array
(4 answers)
Closed 9 months ago.
I'm trying to remove all keys with repeated numbers, I've tried some solutions posted here like the one I'm using in my script but none of it worked for my purpose.
This is my array:
There are at least 4 card IDs repeated.
Array
(
[0] => Array
(
[id_card] => 11883834
[type] => 1
[registed] => 1547610891
)
[1] => Array
(
[id_card] => 20311077
[type] => 1
[registed] => 1547610891
)
[2] => Array
(
[id_card] => 16187903
[type] => 3
[registed] => 1547610891
)
[3] => Array
(
[id_card] => 16354099
[type] => 1
[registed] => 1547610891
)
[4] => Array
(
[id_card] => 21133393
[type] => 4
[registed] => 1547610891
)
[5] => Array
(
[id_card] => 15452852
[type] => 2
[registed] => 1547610891
)
[6] => Array
(
[id_card] => 19775869
[type] => 2
[registed] => 1547610891
)
[7] => Array
(
[id_card] => 20311077
[type] => 1
[registed] => 1547610891
)
[8] => Array
(
[id_card] => 21133393
[type] => 4
[registed] => 1547610891
)
[9] => Array
(
[id_card] => 11883834
[type] => 1
[registed] => 1547610891
)
)
1
At the moment I have something like this:
<?php
$array_data = array_map('unserialize', array_unique(array_map('serialize', $myArray)));
echo '<pre>';
print_r($array_data);
echo '</pre>';
?>
With only 10 keys is working perfectly, but when it goes through this with, for example, 50, 100 keys, no longer works.
Any help appreciated.
So the issue here is that the array_unique solutions expect the entire value to be equivalent - they don't just compare based on your ID field.
Instead, you probably want to loop through the array and keep track of which IDs you've seen, and only take those elements for which you haven't seen the ID before.
function filter_duplicate_id_cards($data) {
$seen = array(); // To keep track of the IDs we've seen
$filtered = array(); // Will hold the result
foreach($data as $item) {
if(array_key_exists($item['id_card'], $seen)) {
// We already encountered this id card before.
continue;
}
// Never-before seen id card, append it to the result and set the key in $seen
$filtered[] = $item;
$seen[$item['id_card']] = TRUE;
}
return $filtered;
}
Note that this uses the map form of a PHP array, rather than just appending seen IDs to the list form and using something like in_array to check if we've seen the key. That's important for performance reasons, especially if we're going to be working on large datasets - in_array is O(n) with the # of items in the array whereas array_key_exists is O(1).
A more generic version of this function would look like this:
function filter_duplicate_field($data, $field) {
$seen = array(); // To keep track of the keys we've seen
$filtered = array(); // Will hold the result
foreach($data as $item) {
if(array_key_exists($item[$field], $seen)) {
// We already encountered this key before.
continue;
}
// Never-before seen key, append it to the result and set the key in $seen
$filtered[] = $item;
$seen[$item[$field]] = TRUE;
}
return $filtered;
}
You could then call it like $result = filter_duplicate_field($data, 'id_card');.
This doesn't preserve the original input order, but because the data is indexed so I'll assume that that doesn't matter.
With just 3 calls in a one-liner, you assign temporary associative keys from back to front to eliminate latter duplicates (because php does not permit duplicate keys), then optionally remove the temporary keys with array_values(). No iterated function calls. No lookup arrays.
Code: (Demo)
$array = [
['id_card' => 11883834, 'type' => 1, 'registed' => 1547610891],
['id_card' => 20311077, 'type' => 1, 'registed' => 1547610891],
['id_card' => 16187903, 'type' => 3, 'registed' => 1547610891],
['id_card' => 16354099, 'type' => 1, 'registed' => 1547610891],
['id_card' => 21133393, 'type' => 4, 'registed' => 1547610891],
['id_card' => 15452852, 'type' => 2, 'registed' => 1547610891],
['id_card' => 19775869, 'type' => 2, 'registed' => 1547610891],
['id_card' => 20311077, 'type' => 1, 'registed' => 1547610891],
['id_card' => 21133393, 'type' => 4, 'registed' => 1547610891],
['id_card' => 11883834, 'type' => 1, 'registed' => 1547610891]
];
var_export(array_values(array_column(array_reverse($array), null, 'id_card')));
If you change you mind about wanting to keep the first occurrence, you can remove array_reverse(). If the first level keys are irrelevant in the output, you can remove array_values(). These changes would allow the solution to be a one function call task.
p.s. "registered"
I am retrieving data from the database with the help of belong to association using find method in cakephp. It's work perfectly but getting output like Array
(
[0] => Array
(
[PaymentLine] => Array
(
[Amount] => -1000.000
[OpenAmount] => -1000.000
[Narration] =>
)
[Payment] => Array
(
[TXNName] => Receipt-1
[TXNDate] => 2014-08-06
)
)
)
But I have to arrange data like Array
(
[0] => Array
(
[Amount] => -1000.000
[OpenAmount] => -1000.000
[Narration] =>
[TXNName] => Receipt-1
[TXNDate] => 2014-08-06
)
)
For these purpose I used Set::ClassicExtract method but that method not working for me... please help me...
Are you able to simply loop over the collection that is returned by the find method?
Perhaps try doing something like this:
$values = [];
foreach($array_of_arrays as $key => $array)
{
foreach($array as $value)
{
$values[] = $value;
}
}
$values will then contain all the values. The end result that you listed is not really possible to achieve if I understand what you are trying to do. This is because in that example you have duplicate keys for things such as 'id' and 'created'. If you only want to get the Arrays and store them in an array without the key then all you have to do is use:
array_values($array_of_arrays);
which will return the array but with the inner arrays having numeric keys instead of the enum ones.
If (for example) you had stored your data that you are getting back in a array called $dummy_data it would look something like this:
$dummy_data = [
'Profile' => Array
(
'id' => "12",
'user_id' => "121",
'skill' => "Baking Cakes",
'created' => "2007-05-01 10:31:01"
),
'User' => Array
(
'id' => "121",
'name' => "Gwoo the Kungwoo",
'created' => "2007-05-01 10:31:01"
)
];
If you know for a fact that the created values will always be the same for the 'Profile' and 'User' arrays then you can get a final array by using
array_merge($dummy_data['User'], $dummy_data['Profile']);
Is there a way to format the $this->find('all') array into the $this->find('list') in the view? The reason I ask is so that I can pass that new array into the form helper options and then use the $this->find('all') array to build some additional things I need?
Array (
[0] => Array ( [School] => Array ( [id] => 0 [name] => Nature [address] => 112 Main [max_students] => 25 [application_level] => 5 ) )
[1] => Array ( [School] => Array ( [id] => 1 [name] => Math [address] => 112 Smith [max_students] => 25 [application_level] => 0 ) )
[2] => Array ( [School] => Array ( [id] => 2 [name] => Art [address] => 112 Lane [max_students] => 25 [application_level] => 0 ) )
)
So this is the array I get when I do a find('all'). I want to build the array so it looks like:
Array (
[0] => 'Nature'
[1] => 'Math'
[2] => 'Art'
)
This is usually done by the $this->find('list') function. Though the reason I want the whole array is because I need to add the application_level into $this->Form->input() function. This is because I need to add the option of class with the application level attached so I show only the shows with the application level based on the previous selection.
EDIT: Can't I just do $this->find('list', [insert parameters here?]);? I just don't understand how you set up the additional parameters?
If your query isn't overly complicated and isn't going to return a excessive number of results, just run it twice (once for find all and once for find list).
Find all, list, first, whatever are all the same in terms of the paramaters you pass in. E.g.:
$this->Model->find('all', array(
'conditions' => array(
'field' => 500,
'status' => 'Confirmed'
),
'order' => 'id ASC'
));
... you literally replace all with list. In your case, probably easiest to do it twice, once for each. Like this:
$parameters = array(
'conditions' => array(
'field' => 500,
'status' => 'Confirmed'
),
'order' => 'id ASC'
);
$alldata = $this->Model->find('all', $parameters);
$listdata = $this->Model->find('list', $parameters);
Otherwise, you can loop through it and populate your own list:
$list = array();
foreach($findall as $row) {
$id = $row['id'];
$name = $row['name'];
$list[$id] = $name;
}
$this->set('listdata', $list);
Short answer to your question is that there's no quick, easy way to select all and list from the same query, but you can re use your parameters (conditions, order etc) by passing them in as predefined arrays, or populate your own list.
An alternative answer to creating the results formatted like find('list') from results from find('all') using CakePHP's hash utility:
//where $data is the result of find all
App::uses('Hash', 'Utility');
$ids = Hash::format($data, array('{n}.Model.id'), '{0}'); //ids in an array.
$names = Hash::format($data, array('{n}.Model.name'), '{0}'); //names in an array
$dataAsList = array_combine($ids, $names);
To improve on kai's answer. The Hash class has a method called combine that can do what you're trying to do in only one line
$list = Hash::combine($data,'{n}.Model.id','{n}.Model.name');
the $list will be a flat array like data from find('list');