Understanding the basics of multidimensional arrays - php

I am new to using multidimensional arrays with php, I have tried to stay away from them because they confused me, but now the time has come that I put them to good use. I have been trying to understand how they work and I am just not getting it.
What I am trying to do is populate results based on a string compare function, once I find some match to an 'item name', I would like the first slot to contain the 'item name', then I would like to increment the priority slot by 1.
So when when I'm all done populating my array, it is going to have a variety of different company names, each with their respective priority...
I am having trouble understanding how to declare and manipulate the following array:
$matches = array(
'name'=>array('somename'),
'priority'=>array($priority_level++)
);

So, in what you have, your variable $matches will point to a keyed array, the 'name' element of that array will be an indexed array with 1 entry 'somename', there will be a 'priority' entry with a value which is an indexed array with one entry = $priority_level.
I think, instead what you probably want is something like:
$matches[] = array(name => 'somename', $priority => $priority_level++);
That way, $matches is an indexed array, where each index holds a keyed array, so you could address them as:
$matches[0]['name'] and $matches[0]['priority'], which is more logical for most people.

Multi-dimensional arrays are easy. All they are is an array, where the elements are other arrays.
So, you could have 2 separate arrays:
$name = array('somename');
$priority = array(1);
Or you can have an array that has these 2 arrays as elements:
$matches = array(
'name' => array('somename'),
'priority' => array(1)
);
So, using $matches['name'] would be the same as using $name, they are both arrays, just stored differently.
echo $name[0]; //'somename';
echo $matches['name'][0]; //'somename';
So, to add another name to the $matches array, you can do this:
$matches['name'][] = 'Another Name';
$matches['priority'][] = 2;
print_r($matches); would output:
Array
(
[name] => Array
(
[0] => somename
[1] => Another Name
)
[priority] => Array
(
[0] => 1
[1] => 2
)
)

In this case, could this be also a solution with a single dimensional array?
$matches = array(
'company_1' => 0,
'company_2' => 0,
);
if (isset($matches['company_1'])) {
++$matches['company_1'];
} else {
$matches['company_1'] = 1;
}
It looks up whether the name is already in the list. If not, it sets an array_key for this value. If it finds an already existing value, it just raises the "priority".

In my opinion, an easier structure to work with would be something more like this one:
$matches = array(
array( 'name' => 'somename', 'priority' => $priority_level_for_this_match ),
array( 'name' => 'someothername', 'priority' => $priority_level_for_that_match )
)
To fill this array, start by making an empty one:
$matches = array();
Then, find all of your matches.
$match = array( 'name' => 'somename', 'priority' => $some_priority );
To add that array to your matches, just slap it on the end:
$matches[] = $match;
Once it's filled, you can easily iterate over it:
foreach($matches as $k => $v) {
// The value in this case is also an array, and can be indexed as such
echo( $v['name'] . ': ' . $v['priority'] . '<br>' );
}
You can also sort the matched arrays according to the priority:
function cmp($a, $b) {
if($a['priority'] == $b['priority'])
return 0;
return ($a['priority'] < $b['priority']) ? -1 : 1;
}
usort($matches, 'cmp');
(Sourced from this answer)

$matches['name'][0] --> 'somename'
$matches['priority'][0] ---> the incremented $priority_level value

Like David said in the comments on the question, it sounds like you're not using the right tool for the job. Try:
$priorities = array();
foreach($companies as $company) {
if (!isset($priorities[$company])) { $priorities[$company] = 0; }
$priorities[$company]++;
}
Then you can access the priorities by checking $priorities['SomeCompanyName'];.

Related

Adding values to a multidimensional array PHP

I have tried this now about 20 different ways, set it down and picked it back up several times and I am at a loss for what I am doing wrong. I am trying to create an array of arrays from three separate arrays. The first array I iterate through is a list of dates. Then I iterate through a list of cabins (this is a simple camp scheduling program), and then I randomly assign an activity to each of the cabins from a third array.
The three arrays are $cabins, $activities, and $checkeddates
//swaps key-value so cabin names are keys
$cabins = array_flip( $cabins );
//sets each key value pair to be cabinname=> null
erase_val( $cabins );
foreach ( $checkeddates as $dates ) {
$uberarray[] = $dates;
}
$uberarray = array_flip( $uberarray );
foreach ( $uberarray as $k => $v ) {
$uberarray[$k] = $cabins;
}
At this point, a var_dump shows that I have an array of dates each containing an array of cabins names with null values, from this point I have tried a dozen things and this is just where I left it, trying a process of elimination to figure out what it isn't.
foreach ( $uberarray as $k => $v ) {
shuffle( $activities );
$s = $activities[0];
$uberarray[] = $s;
}
In the end, I was thinking to build the large array (with some additional rules not yet written in to prevent multiple assignments of the same thing and such. And then as one function I would iterate through the established combinations in the array to write it to the database.
Edit: Request for how I want it to look in the end:
array
'ThuJan1st' =>
array
'cabin 1' => randomactivity1
'cabin 2' => randomactivity2
'cabin 3' => randomactivity3
Currently I have 2 out of 3, but I can not seem to randomly add the activities as values.
Edit: This is what #kunal 's suggestion produced:
array
'ThuJan1st' =>
array
'cabin 1' => randomactivity1
'cabin 2' => randomactivity2
'cabin 3' => randomactivity3
array
'FriJan2nd' =>
array
'cabin 1' => randomactivity4
'cabin 2' => Null
'cabin 3' => Null
Once it iterated through activities a single time, nothing else was assigned a value.
foreach ($checkeddates as $date) {
shuffle( $activities );
foreach ($cabins as $cabin) {
foreach ($activities as $activity) {
$uberarray[$date][$cabin] = $activity;
}
}
}
EDIT: The above answer is incorrect. It assigns the same activity to each date/cabin pair. The below answer should give you what you are looking for.
$checkeddates = array('ThuJan1st');
$cabins = array('cabin 1','cabin 2','cabin 3');
foreach ($checkeddates as $date) {
$activities = array('randomactvitiy1','randomactivity2','randomactivity3');
shuffle( $activities );
foreach ($cabins as $cabin) {
$uberarray[$date][$cabin] = array_pop($activities);
}
}
var_dump($uberarray);

PHP arrays - retrieving a value when other value is known

I have an array of the following structure:
$some_array = array(
array(
'font' => 'Arial',
'label' => 'Arial'
),
array(
'font' => 'PT+Sans:400',
'label' => 'PT Sans'
)
);
Let's say that I only know that one item has 'font' value of 'PT+Sans:400' and I need to retrieve the 'label' value of that single item. How can I do it easier than iterating through subarrays?
Since you are already using foreach you just want other alternatives then you can consider this solutions
Solution 1
You can try to filter your search using array_filter
$search = "PT+Sans:400" ;
$array = array_filter($array,function($v)use($search){ return $v['font'] == $search;});
var_dump($array); // returns all found array
Output
array
1 =>
array
'font' => string 'PT+Sans:400' (length=11)
'label' => string 'PT Sans' (length=7)
If you need only the label
$find = array_shift($array); // take only the first
print($find['label']); // output the label
Output
PT Sans
Solution 2
It you are not interested in return the array and all you want is just the label then you should consider array_reduce
$search = "PT+Sans:400" ;
$results = array_reduce($array,function($a,$b)use($search){ return $b['font'] == $search ? $b['label'] : null ; });
print($results);
Output
PT Sans
You need to iterate through the subarrays. Alternatively, if you have control over the data structure where this is getting stored, consider using a hash table (associative array) and then you can just check if a particular key is set.
Keep it simple:
function findLabel($source, $font)
{
foreach ($source as $item) {
if ($item['font'] == $font) {
return $label;
}
}
return null;
}
Usage:
$label = findLabel($some_array, 'PT+Sans:400');

Find value of sibling key in php array

I have an array in PHP, here is a snippet:
$locations = array(
array(
"id" => 202,
"name" => "GXP Club - Fable"
),
array (
"id" => 204,
"name" => "GXP Club - Gray"
)
);
What I know (from a GET) is the ID (202). What I would like to display is
"Showing results for "
( where $locations[?][id] = $_GET['id'] { echo $locations[?][name] } )
- if you will pardon my use of pseudo code.
Not sure what function is best or if I need to loop over the whole array to find that. Thanks.
Edit: for further clarification. I need to learn the [name] given the [id]
foreach( $locations as $arr ) {
if($arr['id'] == $_GET['id']) {
echo $arr['name'];
break;
}
}
That should do the trick.
While looping over the array is the solution for the problem as described, it seems more optimal to change your array to be $id=>$name key-value pairs, instead of named key values if that's all the data in the array, e.g.:
$locations = array( '202' => 'GXP Club - Fable',
'204' => 'GXP Club - Gray',
)
Alternatively, if there's more data, I'd switch to a nested data structure, e.g.:
$locations = array( '202' => array( 'name' => 'GXP Club - Fable', 'prop2' =>$prop2, etc),
'204' => array( 'name' => 'GXP Club - Gray', 'prop2' =>$prop2, etc),
)
That makes it so you can access data via ID (e.g. $locations[$id]['name']), which seems to be what you'd generally be wanting to do.
You can use array_map function which applies your custom action to each element in given array.
array_map(
function($arr) { if ($arr['id'] == $_GET['id']) echo $arr['name']; },
$locations
);
Doing this with PHP's built-in array functions* avoids a foreach loop:
<?php
$locations = [["id"=>202, "name"=>"GXP Club - Fable"], ["id"=>204, "name"=>"GXP Club - Gray"]];
$col = array_search(array_column($locations, "id"), $_GET["id"]);
echo $locations[$col]["name"];
Or, using a different method:
<?php
$locations = [["id"=>202, "name"=>"GXP Club - Fable"], ["id"=>204, "name"=>"GXP Club - Gray"]];
$result = array_filter($locations, function($v){ return $v["id"] == $_GET["id"]; });
echo array_shift($result)["name"];
* Notably, array_column() was not available until PHP 5.5, released 10 months after this question was asked!

Replace array key integers with string

$string = "php, photoshop, css";
I'm producing an array from the comma separated values above using the str_getcsv() function:
$array = str_getcsv($string);
Result:
Array ( [0] => php [1] => photoshop [2] => css )
How can I replace the key integers with a string tag for all elements like seen below?
Array ( [tag] => php [tag] => photoshop [tag] => css )
Edit: if not possible what alternative can I apply? I need the array keys to be identical for a dynamic query with multiple OR clauses
e.g.
SELECT * FROM ('posts') WHERE 'tag' LIKE '%php% OR 'tag' LIKE '%photoshop% OR 'tag' LIKE '%css%'
I'm producing the query via a function that uses the array key as a column name and value as criteria.
That is not possible. You can have only one item per key. But in your example, the string "tag" would be the key of every item.
The other way arround would work. So having an array like this:
array('php' => 'tag', 'photoshop' => 'tag', 'css' => 'tag');
This might help you, if you want to save the "type" of each entry in an array. But as all the entries of your array seems to be from the same type, just forget about the "tag" and only store the values in a numeric array.
Or you can use a multidimensional array within the numeric array to save the type:
array(
0 => array( 'type' => 'tag', 'value' => 'php' ),
1 => array( 'type' => 'tag', 'value' => 'photoshop' ),
2 => array( 'type' => 'tag', 'value' => 'css' )
);
But still using just an numeric array should be fine if all the entries have the same type. I can even think of a last one:
array(
'tag' => array('php', 'photoshop', 'css')
);
But even if I repeat myself: Just use an ordinary array and name it something like $tag!
BTW: explode(', ', %string) is the more common function to split a string.
To build SQL statement you might do something like this:
// ... inside you build function
if(is_array($value)){
$sql .= "'".$key."' LIKE '%."implode("%' OR '".$key."' LIKE '%", $value)."%'";
} else {
$sql .= "'".$key."' LIKE '%".$value."%'";
}
This might look confusing but it's much cleaner than runnig into two foreach-loops building the query.
That won't work. Your array keys have to be unique, or subsequent additions will simply overwrite the previous key.
As the others said, keys have to be unique. Otherwise, which element should be returned if you access $arr['tag']? If you now say "all of them", then create a nested array:
$array = array();
$array['tag'] = str_getcsv($string);
The value $array['tag'] will be another array (the one you already have) with numerical keys. This makes, because you have a list of tags and lists can be represented as arrays too.
Understanding arrays is very important if you want to work with PHP, so I suggest to read the array manual.
Assuming you know the size of your array beforehand
$tags = array("tag1","tag2","tag3");
$data = array("php","photoshop","css");
$myarray = array();
for ($i=0; $i<count($data); $i++) {
$myarray[$i] = array($data[$i], $tags[$i]);
}
Then
echo $myarray[0][0] . ", " . $myarray[0][1];
Outputs:
php, tag1

Retrieve value of child key in multidiensional array without knowing parent key

Given this multidimensional array, I'm trying to retrieve the value of one of the child keys:
$movieCast = Array(
'1280741692' => Array(
...
, 'userid' => 62
, 'country_id' => '00002'
...
)
, '1280744592' => Array(
...
, 'userid' => 62
, 'country_id' => '00002'
...
)
)
How can I retrieve the value of country_id?
The top-level array key could be anything and the value of country_id will always be the same for a specific user. In this example, user #62's country_id will always be 00002.
You have to iterate through the outer array:
foreach ($outer as $inner) {
//do something with $inner["country_id"]
}
Another option is to build an array with the contry_ids (example uses PHP >=5.3 functionality, but that can be worked around easily in earlier versions):
array_map(function ($inner) { return $inner["country_id"]; }, $outer);
EDIT If the ids are all the same, even easier. Do:
$inner = reset($outer); //gives first element (and resets array pointer)
$id = $inner["country_id"];
a more general-purpose solution using php 5.3:
function pick($array,$column) {
return array_map(
function($record) use($column) {
return $record[$column];
},
$array
);
}
You need to use this:
array_column($movieCast, 'country_id')
The result will be:
array (
0 => '00002',
1 => '00002',
)

Categories