PHP: How to flatten a multidimensional array by duplicate values - php

I have the following array:
array(3) {
[0]=>
array(2) {
["label"]=> string(10) "Chardonnay"
["value"]=> int(245)
}
[1]=>
array(2) {
["label"]=> string(10) "Chardonnay"
["value"]=> int(33)
}
[2]=>
array(2) {
["label"]=> string(10) "Chardonnay"
["value"]=>int(175)
}
[3]=>
array(2) {
["label"]=> string(10) "Stein"
["value"]=>int(195)
}
}
How would I go about "filtering" this array so that it looks like this:
array(2) {
[0]=>
array(2) {
["label"]=> string(5) "Chardonnay"
["value"]=> int(245)
}
[1]=>
array(2) {
["label"]=> string(10) "Stein"
["value"]=>int(195)
}
}
So in essence, I want to remove array elements by value where the value is not unique.
I don't even know where to start. Please assist?

Since keys must be unique, you can index on the label and you will only have one of each:
$result = array_column($array, null, 'label');
If you just want a single dimension with unique values, extract all labels and then make it unique:
$result = array_unique(array_column($array, 'label'));
If this array is coming from a database query then you would do it in the query instead.

You can use this code:
<?php
$arr = [
[
"label"=> "Chardonnay",
"value"=> 245,
],
[
"label"=> "Chardonnay",
"value"=> 33,
],
[
"label"=> "Chardonnay",
"value"=> 75,
],
[
"label"=> "Stein",
"value"=> 195,
],
];
$arr = array_intersect_key($arr,array_unique(array_column($arr,'label')));
print_r($arr);
It will remove duplicates, then intersect the keys (0,3 in this case) with the original array. An alternative to preserve the original keys.

Related

Combing matched keys in an array

Edited
I get the combined item_ids now, but not the single item_ids.
I have an array with three keys.
$searchArray = {
[0]=> array(3) {
["keyword"]=> string(7) "history"
["url"]=> string(7) "history"
["item_id"]=> string(2) "16"
}
[1]=> array(3) {
["keyword"]=> string(4) "past"
["url"]=> string(4) "past"
["item_id"]=> string(2) "16"
}
[89]=> array(3) {
["keyword"]=> string(10) "biomedical"
["url"]=> string(10) "biomedical"
["item_id"]=> string(2) "34"
}
[93]=> array(3) {
["keyword"]=> string(10) "biomedical"
["url"]=> string(10) "biomedical"
["item_id"]=> string(2) "35"
}
I want to combine the options that have the same keyword/url.
Just need to check if keyword matches.
The final format needs to be something that jquery autocomplete can accept, where I can assign the text to keyword and the value to url, id to the item_id.
There were only two keys in the array before and I would combine matches this way.
foreach ($searchArray as $row)
{
$combineMatches[ $row['keyword'] ][] = $row['item_id'];
}
result after using json_encode():
"anthropologist":["27","37"],
"biomedical":["34","35"],
"m.s.":["18","19","23"]
What I currently have:
$combineMatches = array();
foreach ($searchArray as $row)
{
$match =
array_search($row['keyword'],array_column($combineMatches,'keyword'));
if($match){
$combineMatches[$match]['item_id']+= $row['item_id'];
}else{
array_push($combineMatches, [
'keyword' => $row['keyword'],
'url' => $row['url'],
'item_id' => array_push($row['item_id'])
]);
}
}
Result:
[7]=> array(3)
{
["keyword"]=> string(8) "theology"
["url"]=> string(8) "theology"
["item_id"]=> NULL
}
[13]=> array(3)
{
["keyword"]=> string(7) "writing"
["url"]=> string(7) "writing"
["item_id"]=> NULL
}
How do I add to the array column of just item_id ? Which I see is a string, but I need as an array.
This gets JSON encoded in the end of the PHP and read by jquery autocomplete.
Thank you for pointing out the string/array issue.
I changed how to add to the third key if there is a match, and if there isn't a match the solution was changing the array_push to just array.
$combineMatches = array();
foreach ($searchArray as $row)
{
$match=array_search($row['keyword'],array_column($combineMatches,'keyword'));
if($match){
$combineMatches[$match]['item_id'][] = $row['item_id'];
}else{
array_push($combineMatches, [
'keyword' => $row['keyword'],
'url' => $row['url'],
'item_id' => array($row['item_id'])
]);
}
}

Merge 2d arrays with same index value

How can I merge one array inside another 2d array based on a unique value that is shared on both 2d array?
Arrays:
$arr1 = [
"First" =>[
"Name" => "John",
"Id" => 123
],
"Second" =>[
"Name" => "Peter",
"Id" => 45
]
];
$arr2 = [
"First" =>[
"Age" => 34,
"Id" => 123
],
"Second" =>[
"Age" => 24,
"Id" => 45
]
];
$n = array_merge($arr1, $arr2);
Current output when var_dump $n:
array(2) {
["First"]=>
array(2) {
["Age"]=>
int(34)
["Id"]=>
int(123)
}
["Second"]=>
array(2) {
["Age"]=>
int(24)
["Id"]=>
int(45)
}
}
Desired output:
array(2) {
["First"]=>
array(2) {
["Name"]=>
String("John")
["Age"]=>
int(34)
["Id"]=>
int(123)
}
["Second"]=>
array(2) {
["Name"]=>
String("Peter")
["Age"]=>
int(24)
["Id"]=>
int(45)
}
}
Ofcourse just by merging the two arrays wont fix my issue, but i was just wondering what approach I should take to do this.
Assuming this structure of your arrays, you can use array_replace_recursive.
$n = array_replace_recursive($arr1, $arr2);
Fiddle: https://3v4l.org/IPGsl
Some people can say that you can use array_merge_recursive, but no. As you have same key (Id) in both arrays, resulting array will have not the structure you expect. But in case you have different keys in both arrays - array_merge_recursive is an option too.

Best way to implode multidimensional array

I see some questions but no work to me.
In a for loop i receive an array like that:
array(1) { [0]=> array(1) { [0]=> string(1) "4" } }
array(1) { [0]=> array(2) { [0]=> string(1) "3" [1]=> string(1) "4" } }
array(1) { [0]=> array(7) { [0]=> string(1) "1" [1]=> string(1) "2" [2]=> string(2) "30" [3]=> string(2) "43" [4]=> string(2) "65" [5]=> string(2) "53" [6]=> string(3) "634" } }
I need implode that values with "-", my desired output isa string:
4
3-4
2-30-43-65-53-634
I try some ways, but no work, some ideia for do it simple?
If it is a two dimensional array and would like to output all elements, you could use a foreach loop and output the implode of each like so:
$mainArray = [
[4],
[3, 4],
[2, 30, 43, 65, 53, 634]];
foreach($mainArray as $key => $secArray){
echo implode('-', $secArray) . '<br/>';
}
PHP Implode
Notice the return type of implode is a string.

PHP ARRAY get index of item for certain value

I have these 2 arrays $fonts['google'] and $data['value'] with the following content:
var_dump ($fonts['google']) outputs
array(4) {
[0]=> array(3) { ["family"]=> string(7) "ABeeZee" ["variants"]=> array(2) { [0]=> string(7) "regular" [1]=> string(6) "italic" } ["subsets"]=> array(1) { [0]=> string(5) "latin" } }
[1]=> array(3) { ["family"]=> string(4) "Abel" ["variants"]=> array(1) { [0]=> string(7) "regular" } ["subsets"]=> array(1) { [0]=> string(5) "latin" } }
[2]=> array(3) { ["family"]=> string(13) "Abril Fatface" ["variants"]=> array(1) { [0]=> string(7) "regular" } ["subsets"]=> array(2) { [0]=> string(5) "latin" [1]=> string(9) "latin-ext" } }
[3]=> array(3) { ["family"]=> string(8) "Aclonica" ["variants"]=> array(1) { [0]=> string(7) "regular" } ["subsets"]=> array(1) { [0]=> string(5) "latin" } }
}
var_dump ($data['value']) outputs
array(4) {
["size"]=> int(17)
["family"]=> string(3) "Exo"
["style"]=> string(3) "200"
["subsets"]=> string(5) "latin"
}
Now I get the $data['value']['family'] = 'Abel' from my database.
Questions:
How can I get the ['variants'] for the given $data['value']['family'] value?
How can I get the index in $fonts['google'] for the sub-array where the $data['value']['family'] value is?
PHP supports Associative Arrays which let you use a (string) key rather than a numeric index for each element. These arrays are akin to javascript objects, Objective-C dictionaries, java HashMaps, etc.
That makes scenarios like this easy. Do you have control over building the original data array? If you can refactor your storage, set up the arrays like this:
$fonts['google'] = [
["ABeeZee"] => [
["variants"]=>["regular", "italic"],
["subsets"]=>["latin"]
],
["Abel"] => [
["variants"]=>["regular"],
["subsets"]=>["latin"]
],
["Abril Fatface"] => [
["variants"]=>["regular"],
["subsets"]=>["latin", "latin-ext"]
],
["Aclonica"] => [
["variants"]=>["regular"],
["subsets"]=>["latin"]
]
]
extra credit: if you have the original data as in the post, you could convert it:
$newArray = array(); // or just [] in PHP >= 5.3 I believe
foreach($fonts['google'] as $index=>$fontArray) {
$newArray[$fontArray['family']] = $fontArray;
// this leaves a redundant copy of the family name in the subarray
unset $newArray[$fontArray['family']]['family']; // if you want to remove the extra copy
}
Then it becomes trivial. Given a font family name, you just access $fonts['google'][$fontFamilyName] (or $newArray[$fontFamilyName]) using the family name as the array index.

How to add key name in nested arrays?

I have the following array:
array(5) {
[0]=> array(3) {
[0]=> string(10) "2013-09-18"
[1]=> string(75) "Ready For Retina HD: Create Pixel-Perfect Assets For Multiple Scale Factors"
[2]=> string(74) "ready-for-retina-hd-create-pixel-perfect-assets-for-multiple-scale-factors"
}
[1]=> array(3) {
[0]=> string(10) "2010-10-20"
[1]=> string(40) "Taking A Closer Look At Tech Conferences"
[2]=> string(40) "taking-a-closer-look-at-tech-conferences"
}
[2]=> array(3) {
[0]=> string(10) "2014-10-19"
[1]=> string(29) "Wayfinding For The Mobile Web"
[2]=> string(29) "wayfinding-for-the-mobile-web"
}
[3]=> array(3) {
[0]=> string(10) "2014-05-15"
[1]=> string(24) "Freebie: Icons Of Autumn"
[2]=> string(23) "freebie-icons-of-autumn"
}
[4]=> &array(1){
[0]=> string(0) ""
}
}
How would I go about assigning key names to each part of the inner array? E,g date, title, pathname.
I understand you can do something like this to create an array with certain keys, but how does this work with multiple nested arrays? And how can it be assigned after array creation?
$keys = array('Date', 'Title', 'Filepath');
Assuming $array1 is your main array (with 5 values).
foreach($array1 as $a)
{
if (len($a) == 3)
$array2[] = array("Date" => $a[0], "Title" => $a[1], "Filepath" => $a[2]);
}
$array1 = $array2;
Use a foreach.
$new = [];
foreach ($origArray as $inner) {
$new[] = [
"date" => $inner[0],
"title" => $inner[1],
"filepath" => $inner[2]
];
}
$origArray = $new;
This doesn't handle cases where the item does not conform to the "standard" (e.g item 4) but this should get you started.

Categories