I have an array like this one
$state[1]='FG';
$state[2]='BU';
$state[3]='CA';
...
$state[150]='YT'
What I need is to have the $state array ordered from A to Z and maintain, in some structure, the original order of the array.
Something like:
$state_ordered['BU']=2;
$state_ordered['CA']=3;
and so on.
I have the array in the first form in an include file: which is the most performant way and which is the related structure to use in order to have the best solution?
The include is done at each homepage opening...
Thanks in advance,
A.
Well, you can array_flip the array, thus making 'values' be the original indexes, and then sort it by keys...
$b = array_flip($a);
ksort($b);
then work with $b keys , but the values reflect original order
You want array_flip(), which switches the key and value pairs.
Example #2 from the link:
$trans = array("a" => 1, "b" => 1, "c" => 2);
$trans = array_flip($trans);
print_r($trans);
Outputs:
Array
(
[1] => b
[2] => c
)
PHP has quite a few functions for sorting arrays. You could sort your array alphabetically by the values it holds by using asort() and then retrieve the index using array_search()
as such:
?php
$state[1]='FG';
$state[2]='BU';
$state[3]='CA';
asort($state);
$key = array_search('BU',$state);
print $state[$key] . PHP_EOL;
print_r($state);
this will output
BU
Array
(
[2] => BU
[3] => CA
[1] => FG
)
which as you can see keeps the original index values of your array. This does mean however that when you loop over your array without using the index directly, like when you use foreach that you then loop over it in the resorted order:
foreach($state as $key=>$value){
print "$key: $value" . PHP_EOL;
}
2: BU
3: CA
1: FG
You'd need to use ksort on the array first to sort it by index again before getting the regular foreach behaviour that you'd probably want/expect.
ksort($state);
foreach($state as $key=>$value){
print "$key: $value" . PHP_EOL;
}
1: FG
2: BU
3: CA
Looping using a for structure with numeric index values always works correcty of course. Be warned that these functions get passed your array by reference, meaning that they work on the 'live array' and not on a copy, you'll need to make your own copy first if you want one, more info in References Explained.
Related
I have the following scenario
$elementsInPairs = ["xyz","xxx","yyy","zzz"];
$valuesInPair =[4,2,3,1];
and i need to sort the second array which would give me
[1,2,3,4]
which i can do by
sort($valuesInPair)
but i need the same to happen in first array as well, based on the sorting of the second array
["zzz","xxx","yyy","xyz"];
EDIT
As i had to fix it urgently, i guess i wasn't able to share more information, and the question seemed vague
basically the idea is that i have two sets of arrays, same number of elements in all cases, and they are linked to each other, The second array is a set of order IDs. and first array is set of names,
so in the above example, i have
4 relates to xyz
2 relates to xxx
3 relates to yyy
1 relates to zzz
So i need to sort based on IDs, and have the same order reflect in the first array as well,
so the final result would be,
["zzz","xxx","yyy","xyz"];
which is sorted based on
[1, 2, 3, 4];
Hopefully this clears things above
You can achieve this by using array_multisort method.
array_multisort($valuesInPair, SORT_ASC, $elementsInPair);
Use this below code, this does exactly what you're looking for.
$elementsInPairs = ["xyz","xxx","yyy","zzz"];
$valuesInPair =[4,2,3,1];
$data = array_combine($elementsInPairs,$valuesInPair);
asort($data);
$dumpdata = [];
foreach($data as $x => $x_value) {
$dumpdata[] = $x;
}
print_r($dumpdata);
I hope this helps you.
You kan do like this :
<?php
$elementsInPairs = ["xyz","xxx","yyy","zzz"];
$valuesInPair =[4,2,3,1];
//use [asort][1] - Sort an array in reverse order and maintain index association
asort($valuesInPair);
// and make a new array to sort elementsInPairs
$newelementsInPairs = array();
foreach($valuesInPair as $key=>$val){
$newelementsInPairs[] = $elementsInPairs[$key];
}
print_r(implode(",",$valuesInPair)."\n");
print_r(implode(",",$newelementsInPairs));
/** Output
1,2,3,4
zzz,xxx,yyy,xyz
**/
Hi please combine two array and sort
$newArray =array_combine($valuesInPair,$elementsInPairs);
then sort($newArray);
You can use array_combine(), ksort() and array_values():
<?php
$elementsInPairs = ["xyz","xxx","yyy","zzz"];
$valuesInPair = [4,2,3,1];
$newArray = array_combine($valuesInPair, $elementsInPairs);
ksort($newArray);
$sortedElements = array_values($newArray);
print_r($sortedElements);
will output
Array
(
[0] => zzz
[1] => xxx
[2] => yyy
[3] => xyz
)
Question has been updated to clarify
For simple arrays, I find it convenient to use $arr[$key]++ to either populate a new element or increment an existing element. For example, counting the number of fruits, $arr['apple']++ will create the array element $arr('apple'=>1) the first time "apple" is encountered. Subsequent iterations will merely increment the value for "apple". There is no need to add code to check to see if the key "apple" already exists.
I am populating an array of arrays, and want to achieve a similar "one-liner" as in the example above in an element of the nested array.
$stats is the array. Each element in $stats is another array with 2 keys ("name" and "count")
I want to be able to push an array into $stats - if the key already exists, merely increment the "count" value. If it doesn't exist, create a new element array and set the count to 1. And doing this in one line, just like the example above for a simple array.
In code, this would look something like (but does not work):
$stats[$key] = array('name'=>$name,'count'=>++);
or
$stats[$key] = array('name'=>$name,++);
Looking for ideas on how to achieve this without the need to check if the element already exists.
Background:
I am cycling through an array of objects, looking at the "data" element in each one. Here is a snip from the array:
[1] => stdClass Object
(
[to] => stdClass Object
(
[data] => Array
(
[0] => stdClass Object
(
[name] => foobar
[id] => 1234
)
)
)
I would like to count the occurrences of "id" and correlate it to "name". ("id" and "name" are unique combinations - ex. name="foobar" will always have an id=1234)
i.e.
id name count
1234 foobar 55
6789 raboof 99
I'm using an array of arrays at the moment, $stats, to capture the information (I am def. open to other implementations. I looked into array_unique but my original data is deep inside arrays & objects).
The first time I encounter "id" (ex. 1234), I'll create a new array in $stats, and set the count to 1. For subsequent hits (ex: id=1234), I just want to increment count.
For one dimensional arrays, $arr[$obj->id]++ works fine, but I can't figure out how to push/increment for array of arrays. How can I push/increment in one line for multi-dimensional arrays?
Thanks in advance.
$stats = array();
foreach ($dataArray as $element) {
$obj = $element->to->data[0];
// this next line does not meet my needs, it's just to demonstrate the structure of the array
$stats[$obj->id] = array('name'=>$obj->name,'count'=>1);
// this next line obviously does not work, it's what I need to get working
$stats[$obj->id] = array('name'=>$obj->name,'count'=>++);
}
Try checking to see if your array has that value populated, if it's populated then build on that value, otherwise set a default value.
$stats = array();
foreach ($dataArray as $element) {
$obj = $element->to->data[0];
if (!isset($stats[$obj->id])) { // conditionally create array
$stats[$obj->id] = array('name'=>$obj->name,'count'=> 0);
}
$stats[$obj->id]['count']++; // increment count
}
$obj = $element->to->data is again an array. If I understand your question correctly, you would want to loop through $element->to->data as well. So your code now becomes:
$stats = array();
foreach ($dataArray as $element) {
$toArray = $element->to->data[0];
foreach($toArray as $toElement) {
// check if the key was already created or not
if(isset($stats[$toElement->id])) {
$stats[$toElement->id]['count']++;
}
else {
$stats[$toElement->id] = array('name'=>$toArray->name,'count'=>1);
}
}
}
Update:
Considering performance benchmarks, isset() is lot more faster than array_key_exists (but it returns false even if the value is null! In that case consider using isset() || array_key exists() together.
Reference: http://php.net/manual/en/function.array-key-exists.php#107786
I have a PHP array that looks like that:
$array = Array
(
[teamA] => Array
(
[188555] => 1
)
[teamB] => Array
(
[188560] => 0
)
[status] => Array
(
[0] => on
)
)
In the above example I can use the following code:
echo $array[teamA][188555];
to get the value 1.
The question now, is there a way to get the 188555 in similar way;
The keys teamA, teamB and status are always the same in the array. Alse both teamA and teamB arrays hold always only one record.
So is there a way to get only the key of the first element of the array teamA and teamB?
More simple:
echo key($array['teamA']);
More info
foreach($array as $key=>$value)
{
foreach($value as $k=>$v)
{
echo $k;
}
}
OR use key
echo key($array['teamA']);
echo array_keys($array['teamA'])[0];
Refer this for detailed information from official PHP site.
Use two foreach
foreach($array as $key => $value){
foreach($value as $key1 => $value2){
echo $key1;
}
}
This way, you can scale your application for future use also. If there will be more elements then also it would not break application.
You can use array_flip to exchange keys and values. So array('12345' => 'foo') becomes array('foo' => '12345').
Details about array_flip can be studied here.
I would suggest using list($key, $value) = each($array['teamA']) since the question was for both key and value. You won't be able to get the second or third value of the array without a loop though. You may have to reset the array first if you have changed its iterator in some way.
I suppose the simplest way to do this would be to use array_keys()?
So you'd do:
$teamAKey = array_shift(array_keys($array['TeamA']));
$teamBKey = array_shift(array_keys($array['TeamB']));
Obviously your approach would depend on how many times you intend to do it.
More info about array_keys and array_shift.
First time trying to find something in an array using an array as both a needle and a haystack. So, example of 2 arrays:
My Dynamically formed array:
Array (
[0] =>
[1] => zpp
[2] => enroll
)
My Static comparison array:
Array (
[0] => enroll
)
And my in_array() if statement:
if (in_array($location_split, $this->_acceptable)) {
echo 'found';
}
$location_split; // is my dynamic
$this->_acceptable // is my static
But from this found is not printed out, as I'd expect it to be? What exactly am I failing on here?
If i'm understanding you right, you want to see whether the first array's entries are present in the second array.
You might look at array_intersect, which would return you an array of stuff that's present in all the arrays you pass it.
$common = array_intersect($this->_acceptable, $location_split);
if (count($common)) {
echo 'found';
}
If the count of that array is at least 1, then there's at least one element in common. If it's equal to your dynamic array's length, and the array's values are distinct, then they're all in there.
And, of course, the array will be able to tell you which values matched.
Because there is no element in your array containing array('enroll') in it (only 'enroll').
Your best bet would be to use array_diff(), if the result is the same as the original array, no match is found.
You are interchanging the parameters for in_array (needle & haystack). It needs to be,
if(in_array($this->_acceptable, $location_split))
{
echo 'found';
}
Edit: Try using array_intersect.
Demo
Assume that i have the following arrays containing:
Array (
[0] => 099/3274-6974
[1] => 099/12-365898
[2] => 001/323-9139
[3] => 002/3274-6974
[4] => 000/3623-8888
[5] => 001/323-9139
[6] => www.somesite.com
)
Where:
Values that starts with 000/, 002/ and 001/ represents mobile (cell) phone numbers
Values that starts with 099/ represents telephone (fixed) numbers
Vales that starts with www. represents web sites
I need to convert given array into 3 new arrays, each containing proper information, like arrayTelephone, arrayMobile, arraySite.
Function in_array works only if i know whole value of key in the given array, which is not my case.
Create the three empty arrays, loop through the source array with foreach, inspect each value (regexp is nice for this) and add the items to their respective arrays.
Loop through all the items and sort them into the appropriate arrays based on the first 4 characters.
$arrayTelephone = array();
$arrayMobile = array();
$arraySite = array();
foreach($data as $item) {
switch(substr($item, 0, 4)) {
case '000/':
case '001/':
case '002/':
$arrayMobile[] = $item;
break;
case '099/':
$arrayTelephone[] = $item;
break;
case 'www.':
$arraySite[] = $item;
break;
}
}
You can loop over the array and push the value to the correct new array based on your criteria. Example:
<?php
$fixed_array = array();
foreach ($data_array as $data) {
if (strpos($data, '099') === 0) {
$fixed_array[] = $data;
}
if ....
}
Yes i actually wrote the full code with preg_match but after reading some comments i accept that its better to show the way.
You will create three different arrays named arrayTelephone, arrayMobile, arraySite.
than you will search though your first array with foreach or for loop. Compare your current loop value with your criteria and push the value to one of the convenient new arrays (arrayTelephone, arrayMobile, arraySite) after pushing just continue your loop with "continue" statement.
You can find the solution by looking add the Perfect PHP Guide