How to custom sort array indexes in php? - php

I have a multidimensional array or arrays which I also use in my configuration file. The file is also manually edited so I want some of the keys to have fixed position. The code reads configuration file with this array, modifies, insert keys etc and then saves it back. On save I sort the keys but now I found that it is not good enough.
Is there any way to have
the key 'full_name' always as the first key
the key 'version' as second one
and the rest of the keys to be sorted alphabetically?
Sample of the array....
array (
'skroob' =>
array (
'ssh' => 'skroob',
'codebase_path' => '/srv/www/htdocs/imacs/radek/4.0.1',
'ssh_status' => 'ok',
'version' => '4.0.1',
'ssh_last_access' => '2012-Feb-17 10:07:26',
'edu_url' => 'https://testing/imacs/radek/4.0.1',
'full_name' => 'skroob 4.0.1',
),
'testing' =>
array (
'full_name' => 'My beautiful testing server (trunk)',
'version' => 'trunk',
'ssh' => 'testing',
'codebase_path' => '/srv/www/htdocs/imacs/radek/trunk',
'ssh_last_access' => '2012-Feb-17 10:07:26',
'ssh_status' => 'ok',
),
)

Here's one way. It sorts the array alphabetically, by key. Then it reverses the array and unsets the full_name and version keys. Then it adds those keys again, so they get placed at the end of the array. Lastly, it reverses the array again. Kinda hacky but I'm not sure there's a much better way to do what you're asking.
ksort($arr['skroob']);
$arr['skroob'] = array_reverse($arr['skroob']);
$version = $arr['skroob']['version'];
$full_name = $arr['skroob']['full_name'];
unset($arr['skroob']['full_name'], $arr['skroob']['version']);
$arr['skroob']['version'] = $version;
$arr['skroob']['full_name'] = $full_name;
$arr['skroob'] = array_reverse($arr['skroob']);
Another solution is to use uksort and write a small callback function. That would probably look a bit more professional.

Related

Multidimensional Array Not Echoing As Expected

I am setting this array manually:
$schools = array(
'Indiana University'=>array(
'initials'=>'IU',
'color'=>'red',
'directory'=>'indiana'
)
);
But it won't echo "IU" when I use:
echo $schools[0][0];
It does show correctly when I do:
print_r($schools);
I'm sure I'm messing up something dumb, but I have no idea what and I've been staring at it for hours. This array is actually part of a larger array with multiple universities, but when I trim it down to just this, it doesn't work.
PHP arrays support two types of keys - numerical and strings.
If you just push a value onto an array, it will use numerical keys by default. E.g.
$schools[] = 'Indiana University';
echo $schools[0]; // Indiana University
However, when you use string keys, you access the array values using the string key. E.g.
$schools = array(
'Indiana University' => array(
'initials' => 'IU',
'color' => 'red',
'directory' => 'indiana'
)
);
echo $schools['Indiana University']['initials']; // UI

PHP7: Sort an associative array by byte value of the combined value of Key and Value

I am new to PHP programming and I am trying to create a signed request for an Amazon REST request. To properly sign the request, I have to sort the parameter/value pairs by byte value (not alphabetically). They provide a sample set as an example:
Service=AWSECommerceService
AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE
AssociateTag=mytag-20
Operation=ItemLookup
ItemId=0679722769
ResponseGroup=Images%2CItemAttributes%2COffers%2CReviews
Version=2013-08-01
Timestamp=2014-08-18T12%3A00%3A00Z
Sorted Values:
AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE
AssociateTag=mytag-20
ItemId=0679722769
Operation=ItemLookup
ResponseGroup=Images%2CItemAttributes%2COffers%2CReviews
Service=AWSECommerceService
Timestamp=2014-08-18T12%3A00%3A00Z
Version=2013-08-01
So, I created an associative array called $parameters that holds all those values in this syntax:
$parameters = array ( "Service=" => "AWSECommerceService",
"AWSAccessKeyId=" => "AKIAIOSFODNN7EXAMPLE",
"AssociateTag=" => "mytag-20",
"Operation=" => "ItemLookup"
);
Is there a method to sort the combined value of the individual key/value pairs concatenated? Or do I have to combine them into a temporary array, sort them, and then put them back into the associative array?
Any guidance would be greatly appreciated.
I don't know why JYoThl deleted his anwser, ksort will do the job just fine:
$parameters = array(
"Service=" => "AWSECommerceService",
"AWSAccessKeyId=" => "AKIAIOSFODNN7EXAMPLE",
"AssociateTag=" => "mytag-20",
"Operation=" => "ItemLookup",
"ItemId=" => "0679722769",
"ResponseGroup=" => "Images%2CItemAttributes%2COffers%2CReviews",
"Version=" => "2013-08-01",
"Timestamp=" => "2014-08-18T12%3A00%3A00Z"
);
ksort($parameters);
print_r($parameters);
Output:
Array
(
[AWSAccessKeyId=] => AKIAIOSFODNN7EXAMPLE
[AssociateTag=] => mytag-20
[ItemId=] => 0679722769
[Operation=] => ItemLookup
[ResponseGroup=] => Images%2CItemAttributes%2COffers%2CReviews
[Service=] => AWSECommerceService
[Timestamp=] => 2014-08-18T12%3A00%3A00Z
[Version=] => 2013-08-01
)
use ksort() Sort an associative array in ascending order, according to the key:
<?php
$parameters = array ( "Service=" => "AWSECommerceService",
"AWSAccessKeyId=" => "AKIAIOSFODNN7EXAMPLE",
"AssociateTag=" => "mytag-20",
"Operation=" => "ItemLookup"
);
ksort($parameters);
print_r($parameters );
?>

using in_array() with keys and values in arrays?

Let's say I have an array
$array = array(
'username' => "username",
'location' => "location",
'other' => "other");
This array can hold data for many users, so there could be different values for each 'username', 'location', and 'other' fields. How can I use in_array() or another function to determine if a specific username exists in the array already? Because what if a user has a username like "nyc" and a location of "nyc" and I do
in_array("nyc", $array);
How exactly should something like this be approached?
Thank you.
To achieve something that I think is what you want, you can make an array of associative arrays that have the same keys.
<?php
// This syntax will work only on PHP 5.4
$a=[["name"=>"john","age"=>25],["name"=>"philip","age"=>110]];
print_r(array_filter($a, function($item) {return $item["name"] === "john"; }));
?>
Outputs:
Array
(
[0] => Array
(
[name] => john
[age] => 25
)
)
If you just wanted to know if a person named John was in the list, you can just use sizeof/count on the returned array.
This will allow you to have any number of duplicates, and you don't need to specify any keys. Check out the functions: array_filter, array_reduce, array_map. With all of these, you can process your list using closures like in my example above.
Instead of using associative arrays in your array, you could have objects too. Objects are more heavyweight, and need initialization and stuff, so it is grotesque for using them for tiny static (hardcoded) lists. But they may come handy when your data structures grow and you want to make sure every list item has a certain property (the constructor of the class could ensure that everything is initialized). But the good thing is that filter, reduce and map would still work. The "$item" would then be your object.
$users = array( 'user_id' => array('username' => "username",
'location' => "location",
'other' => "other");
user_id is their NUMBER user_id
So you then call $users['####']['username'];
IE:
$users = array( '1' => array('username' => 'Jim',
'location' => 'Florida',
'other' => "other"),
'2' => array('username' => 'Jane',
'location' => 'Maryland',
'other' => "Grapes"));
Then use array_keys() to search for their user_id

PHP multi-dimentional array sort

I have an array that I would like to sort, that should be easy, except that I build my array in a strange manners (for different reasons) that make it hard to sort. Here is my array :
$arrayCEO =array(
'companyName' => array(0=>'name1', 1=>'name2'),
'link' => array (0=>'link1', 1=>'link2'),
'isin' => array (0=>'isin1', 1=>'isin2'),
'mktCap' => array (0=>'mktCap1', 1=>'mktCap2'),
'nbShares' => array (0=>'nbShares1', 1=>'nbShares2'),
'amount' => array (0=>'10', 1=>'20'));
Is that possible to sort by "amount" without breaking the order in the others arrays?
Do you recommend me to rewrite my code to build an array like this one :
$arrayCEO =array(
0 => array ('name' => 'name1', 'link' => 'link1', 'isin' => 'isin1', …),
1 => array ('name' => 'name2', 'link' => 'link2', 'isin' => 'isin2', …));
2 => ...
I know this one would be simple to sort but it's a lot of work to rewrite my piece of code.
Thanks,
Dorian
It makes a lot more sense to rewrite your arrays to store in the more conventional format you described - (It's always better to organise things in decreasing magnitude 'Root > rows > fields' instead of 'Root > fields > rows')
If you didn't want to change you could probably use the usort function and roll your own sorting method, but it might be a bit of work to make it play nicely.

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

Categories