This question already has answers here:
How do I sort a multidimensional array by one of the fields of the inner array in PHP? [duplicate]
(8 answers)
Closed last year.
Question: how to sort multi dimensional array with object?
Status : I've an array as following.
array(3) {
[0]=>
object(Photo_model)#25 (5) {
["id"]=>
int(5)
["file_name"]=>
string(36) "A49361605AE049D687CDC3FEAF7D3236.jpg"
["user_id"]=>
int(1)
["challenge_id"]=>
string(1) "2"
["score"]=>
int(19)
}
[1]=>
object(Photo_model)#28 (5) {
["id"]=>
int(2)
["file_name"]=>
string(36) "A49361605AE049D687CDC3FEAF7D3236.jpg"
["user_id"]=>
int(1)
["challenge_id"]=>
string(1) "2"
["score"]=>
int(10)
}
[2]=>
object(Photo_model)#29 (5) {
["id"]=>
int(3)
["file_name"]=>
string(36) "A49361605AE049D687CDC3FEAF7D3236.jpg"
["user_id"]=>
int(1)
["challenge_id"]=>
string(1) "2"
["score"]=>
int(15)
}
}
I tried to sort above array by score. I created a function as follow.
aarsort (&$array, 'score');
function aarsort (&$array, $key) {
$sorter=array();
$ret=array();
reset($array);
foreach ($array as $ii => $va) {
$sorter[$ii]=$va[$key];
}
arsort($sorter);
foreach ($sorter as $ii => $va) {
$ret[$ii]=$array[$ii];
}
$array=$ret;
}
But it is not working. How can I sort the multidimensional array by key (score)?
result should be by id => 5,3,2
Your array is only 1 dimensional, and there is an object in each array item.
After all, to sort a 1D array consisting of objects, and sort by a certain property of the objects, use usort
usort($array, function($a, $b) {
return $a->score - $b->score
});
To get id => 5, 3, 2 from above, just loop through the array from the above code and access the property to get it
$ids = array();
foreach ($array as $item) {
$ids[] = $item->id;
}
var_dump($ids);
And I am not sure if the order is right. If it turns out to be reverse order, just negate the result of the closure in the usort function.
It just example.
//$newarray for store all array id
//$array is your previous array . You just enter your all index whose key id store in new array
$newarray = array();
foreach($array as $obj => $id)
{
$newarray[] = $id[$key];
}
array_multisort($newarray,SORT_ASC,$array);
I've done this problem by php.net
// Obtain a list of columns
foreach ($array as $key => $row) {
$_score[$key] = $row->score;
}
// Sort the data with volume descending, edition ascending
// Add $data as the last parameter, to sort by the common key
array_multisort($_score, SORT_DESC, $array);
Related
I've got a multidimensional array as follows:
array(2) {
[0]=>
array(8) {
["id"]=>
string(3) "117"
["promotiontype_id"]=>
string(1) "1"
["groupa_id"]=>
string(3) "390"
["groupb_id"]=>
string(3) "390"
["varx"]=>
string(1) "2"
["vary"]=>
string(1) "1"
["varz"]=>
string(0) ""
["totaldiscount"]=>
float(6.5)
}
[1]=>
array(8) {
["id"]=>
string(3) "117"
["promotiontype_id"]=>
string(1) "1"
["groupa_id"]=>
string(3) "390"
["groupb_id"]=>
string(3) "390"
["varx"]=>
string(1) "2"
["vary"]=>
string(1) "1"
["varz"]=>
string(0) ""
["totaldiscount"]=>
float(7.0)
}
}
So, as you'll see, the first array has a "totaldiscount" of 6.5, the second has 7.0.
Essentially, I need to remove the array that contains the lowest value, so in this instance, it would be array [0] that gets removed as 6.5 has the lowest "totaldiscount". The array could contain more than 2 sub arrays.
I assume it's something to do with foreaching through, but my brain is going in to meltdown with this one!
Any help would be much appreciated!
I am going to divide your question in 2 parts:
How to find the lowest value of x?
function lowestX($array){
$lowest = 999;
for($array as $var){
if($lowest > $var["totaldiscount"]){
$lowest = $var["totaldiscount"];
}
}
}
How do I remove a value from an array?
Use unsset or function.array-splice
A possible solution is to use usort to sort the arrays by "totaldiscount"
Then get the lowest "totaldiscount" value from the sorted arrays.
Then you can loop the sorted arrays (in case there are multiple "totaldiscount" values which have the same lowest value) and unset the array(s) which contains the $lowestTotaldiscount by using the array key.
For example:
<?php
function cmp($a, $b)
{
return ($a["totaldiscount"] < $b["totaldiscount"]) ? -1 : 1;
}
usort($arrays, "cmp");
$lowestTotaldiscount = $arrays[0]["totaldiscount"];
foreach($arrays as $key => $array) {
if ($array["totaldiscount"] === $lowestTotaldiscount) {
unset($arrays[$key]);
}
}
Demo
here is solution of your problem .Simply use array_multisort & unset as given below .
`
$yourArray = array(
array(
"id"=>"117",
"promotiontype_id"=>"1",
"groupa_id"=>"390",
"groupb_id"=> "390",
"varx"=>"2",
"vary"=>"1",
"varz"=> "",
"totaldiscount"=>8.5,
),
array (
"id"=> "117",
"promotiontype_id"=>"1",
"groupa_id"=>"390",
"groupb_id"=>"390",
"varx"=>"2",
"vary"=>"1",
"varz"=>"",
"totaldiscount"=>7.0,
),
array (
"id"=> "117",
"promotiontype_id"=>"1",
"groupa_id"=>"390",
"groupb_id"=>"390",
"varx"=>"2",
"vary"=>"1",
"varz"=>"",
"totaldiscount"=>9.0, )
);
$discount = array();
foreach ($yourArray as $key => $row)
{
$discount[$key] = $row['totaldiscount'];
}
array_multisort($discount, SORT_ASC, $yourArray);
unset($yourArray[0]);
print"<pre>";
print_r($yourArray);`
I have a Php array that have values of times as array values and timestamps as key array is like this:
array(
144454884=>"12:00am", 145454884=>"12:30am", 144474884=>"1:00am", 144454864=>"1:30am", 143354884=>"1:00am", 144654884=>"1:30am", 1444567584=>"2:00am "
);
Timestamp values in above example are not real I wrote an example they are useless anyway unless your timezone matches mine.
Problem:
I need to get "1:00am" and "1:30am" twice I can get repeating values 1 time as shown in answer here:
php return only duplicated entries from an array
I need both repeating values two times with both keys and values being repeated because I need to eliminate those timestamps from week time on my system because of daylight saving a time is repeating and I don't want to show 1:00am at all I just want to show this time as unavailable.
I am not 100% sure what you wanted but this is what I think you need.
Assuming your input array is called $a
$b = array_flip(array_flip($a));
$c = array_diff_key($a, $b);
$b will contain an array of unique values.
$c will contain the elements that were removed.
Results of $b and $c are as follows:
array(5) {
[144454884] = string(7) "12:00am"
[145454884] = string(7) "12:30am"
[143354884] = string(6) "1:00am"
[144654884] = string(6) "1:30am"
[1444567584] = string(7) "2:00am "
}
array(2) {
[144474884] = string(6) "1:00am"
[144454864] = string(6) "1:30am"
}
This code works :
<?php
$array_new = [];
$array_tmp = [];
$array = array(1=>'1233',2=>'12334',3 =>'Hello' ,4=>'hello', 5=>'U');
//loop trough all elements in array and for ever element create key
//For "world" key is "world"
//For "World" key is "world"
//For "WORLD" key is "world"
//So all this cases have same key and differenet representation eg. "world" => ["world","World","WORLD"]
foreach($array as $k => $v){
$index = strtolower($v);
$array_tmp[$index][] = $v;
}
//loop trough new array with new keys and if there are more than one element(> 1) for some key, all of his representations put in new array
foreach($array_tmp as $k => $v){
if(count($v) > 1){
foreach($v as $k2 => $v2){
$array_new[] = $v2;
}
}
}
echo '<pre>';
print_r($array_new);
echo '<pre>';
A possible solution keeping the key information (I will assign the intermediate results to their own variables otherwise it can be confusing to read)
$array = array(
143354883 => "1:00am",
144454884 => "12:00am",
145454884 => "12:30am",
144474884 => "1:00am",
144454864 => "1:30am",
143354884 => "1:00am",
144654884 => "1:30am",
1444567584 => "2:00am ",
0 => 4,
1 => 4,
2 => 4,
3 => "Test",
4 => "TEST",
5 => "test "
);
// Used this array_iunique function: http://stackoverflow.com/questions/2276349/case-insensitive-array-unique
function array_iunique($array) {
return array_intersect_key(
$array,
array_unique(array_map("StrToLower",$array))
);
}
$unique = array_iunique($array);
// Then get the difference by key, that will give you all the duplicate values:
$diff_key = array_diff_key($array, $unique);
// Now we have to find the values that are in the $diff_key and the $unique because we also want to have those:
$correspondingValues = array_uintersect($unique, $diff_key, "strcasecmp");
// Then we have to combine the $duplicate values with the $diff_key and preserve the keys:
$result = array_replace($correspondingValues, $diff_key);
var_dump($result);
Will result in:
array(10) {
[143354883]=>
string(6) "1:00am"
[144454864]=>
string(6) "1:30am"
[0]=>
int(4)
[3]=>
string(4) "Test"
[144474884]=>
string(6) "1:00am"
[143354884]=>
string(6) "1:00am"
[144654884]=>
string(6) "1:30am"
[1]=>
int(4)
[2]=>
int(4)
[4]=>
string(4) "TEST"
}
I have an array from json_decode. And i want to reformat it.
this is my array format.
["Schedule"]=>array(1) {
["Origin"]=>
string(3) "LAX"
["Destination"]=>
string(2) "CGK"
["DateMarket"]=>
array(2) {
["DepartDate"]=>
string(19) "2015-02-01T00:00:00"
["Journeys"]=>
array(6) {
[0]=>
array(6) {
[0]=>
string(2) "3210"
[1]=>
string(14) "Plane Name"
[2]=>
string(8) "20150201"
[3]=>
string(8) "20150201"
[4]=>
string(4) "0815"
[5]=>
string(4) "1524"
}
}
}
And i want change the indexed array to associative with foreach function.
And here is my PHP code
foreach ($response->Schedule['DateMarket']['Journeys'] as $key=>$value) {
$value->Name= $value[1];
}
But i got an error "Attempt to assign property of non-object on line xXx..
My Question is, how to insert a new associative array to indexed array like the example that i've provide.
UPDATE : I've tried this solution
foreach ($response->Schedule['DateMarket']['Journeys'] as $key=>$value) {
$value['Name']=$value[1];
}
But my array format still the same, no error.
In this line:
$value->Name= $value[1];
You expect $value to be both object ($value->Name) and array ($value[1]).
Change it to something like:
foreach ($response->Schedule['DateMarket']['Journeys'] as $key=>$value) {
$response->Schedule['DateMarket']['Journeys'][$key]['Name'] = $value[1];
}
Or even better, without foreach:
$keys = array(
0 => 'Id',
1 => 'Name',
2 => 'DateStart',
3 => 'DateEnd',
4 => 'HourStart',
5 => 'HourEnd',
);
$values = $response->Schedule['DateMarket']['Journeys'];
$response->Schedule['DateMarket']['Journeys'] = array_combine( $keys , $values );
Array_combine makes an array using keys from one input and alues from the other.
Docs: http://php.net/manual/en/function.array-combine.php
Try this:
foreach ($response->Schedule['DateMarket']['Journeys'] as $key=>$value) {
$value['Name'] = $value[1];
}
You want to create new array index, but try to create new object.
foreach ($response->Schedule['DateMarket']['Journeys'] as $key => $value) {
$value['Name'] = $value[1];
}
I have an array of db records that I want to convert from this:
array(2) {
[0]=>
array(1) {
["ID"]=>
string(1) "2"
}
[1]=>
array(1) {
["ID"]=>
string(1) "3"
}
}
To this:
array(2) {
[0]=>
string(1) "2"
[1]=>
string(1) "3"
}
I'm looking for the fastest performing/easiest solution to this.
I couldn't find any PHP functions for this.
On PHP 5.5 or later, the simplest solution would be using PHP's built-in array_column() function.
$ids = array_column($arr, 'ID');
$bas = array();
foreach ($foo as $bar) {
$bas[] = $bar['ID'];
}
print_r($bas);
Where $foo would be you original array and $bas the one you want to convert it to.
I wrote simple test for finding best solution between those:
// foreach
foreach ($array as $element) { $result[] = $element['ID']; }
// array_map
array_map(function($element) { return $element['ID']; }, $array);
// array_push
foreach ($array as $element) { array_push($result, $element['ID']); }
Results:
Test name Repeats Result Performance
foreach 1000 0,009204 sec +0%
array_push 1000 0,015731 sec -70,915%
array_map 1000 0,024891 sec -170,437%
From time to time they are slightly different, but foreach is always the best with outstanding performance results. So, seems #campari answer must be best answer. But i did not tested #kba solution, cause i'm on PHP 5.4. I suspect that array_column algorithm will show superior results.
Test code here: link.
Your input data (enriched with other data-types, -for testing-) and assuming you are using recent PHP versions:
$input = array(
0=>
array(
"ID"=> "2"
),
1=>
array(
"ID"=> "3"
),
"iamnotanarray", 100, null
);
exemplary:
$out = array_map( function($el){ return #current($el);}, $input);
generally:
$out = array_combine(
array_keys($ret)
,array_map( function($el){ return #current($el);}, $ret)
)
output:
var_export($out);
array (
0 => '2',
1 => '3',
2 => NULL,
3 => NULL,
4 => NULL,
)
var_dump($out);
array(5) {
[0]=>
string(1) "2"
[1]=>
string(1) "3"
[2]=>
NULL
[3]=>
NULL
[4]=>
NULL
}
To filter potentially unwanted data types, you may use:
$out = array_filter($out, is_string);
var_dump($out);
array(2) {
[0]=>
string(1) "2"
[1]=>
string(1) "3"
}
I didn't time it (yet), but this is using PHP's native precompiled functions. Speed varies with the gcc compiler optimizations of your PHP executable.
Note: #current is dirty, not recommended and just used for brevity/readability. It would yield the same effect as is_array($el) ? current($el) : NULL;
Try this-
$newArr = array();
foreach($array as $a) // $array is original array
{
array_push($newArr, $a["ID"]);
}
print_r($newArr);
I have an array with 2 kinds of keys, strings and integers. I want to do foreach() on this array and want to do it for numeric keys only. What is the most elegant way of doing it?
Here's a complicated method using array_filter() to return the numeric keys then iterate over them.
// $input_array is your original array with numeric and string keys
// array_filter() returns an array of the numeric keys
// Use an anonymous function if logic beyond a simple built-in filtering function is needed
$numerickeys = array_filter(array_keys($input_array), function($k) {return is_int($k);});
// But in this simple case where the filter function is a plain
// built-in function requiring one argument, it can be passed as a string:
// Really, this is all that's needed:
$numerickeys = array_filter(array_keys($input_array), 'is_int');
foreach ($numerickeys as $key) {
// do something with $input_array[$key']
}
It's much easier though to just foreach over everything:
foreach ($input_array as $key => $val) {
if (is_int($key)) {
// do stuff
}
}
Edit Misread original post and thought I saw "numeric" rather than "integer" keys. Updated to use is_int() rather than is_numeric().
foreach($array as $key => $val) {
if(!is_int($key))
continue;
// rest of the logic
}
This one-liner returns a new array with the values and its numeric keys:
$new_array = array_filter($my_array, 'is_int', ARRAY_FILTER_USE_KEY);
so if we have this:
array(
'fruit' => 'banana'
1 => 'papaya'
)
..we get this:
array(
1 => 'papaya'
)
Using array_filter you must aware if you have value that similar as FALSE.
This is my solution:
function filterArrayKeyInteger(Array $array) {
$integer = array_filter($array, function ($key) {
if ($key === 0 || is_int($key)) {
return true;
}
}, ARRAY_FILTER_USE_KEY);
return array_intersect_key($array, $integer);
}
$a = [0, false, 'aa','bb', 'cc', 'dd' => 'dd', '9.9' => 9.9];
$b = filterArrayKeyInteger($a);
Result of vardump
var_dump(a): array(7) {
[0]=>
int(0)
[1]=>
bool(false)
[2]=>
string(2) "aa"
[3]=>
string(2) "bb"
[4]=>
string(2) "cc"
["dd"]=>
string(2) "dd"
["9.9"]=>
float(9.9)
}
var_dump(b): array(5) {
[0]=>
int(0)
[1]=>
bool(false)
[2]=>
string(2) "aa"
[3]=>
string(2) "bb"
[4]=>
string(2) "cc"
}