php array sorting on child element - php

I am trying to sort an array based on the first [0] child element. But in my code the keys are being replaced by the array number in the sort:
$myArray = array(
'my last row' => array(
'0' => 'ZZZZ',
'1' => 'AAAA'
),
'the first row' => array(
'0' => 'AAAA'
)
);
usort($myArray, 'cmp' ) ;
var_dump($myArray);
function cmp ($a, $b) {
return ( ( $a[0] > $b[0] ) ? 1 : -1 );
}
result:
array(2) {
[0]=> // should be ['the first row'] *not* [0]
array(1) {
[0]=>
string(4) "AAAA"
}
[1]=> // should be ['my last row'] *not* [1]
array(2) {
[0]=>
string(4) "ZZZZ"
[1]=>
string(4) "AAAA"
}
}
The sort order itself appears to be working as expected.
I would like to see the following:
the first row => AAAA
my last row => ZZZZ, AAAA
This is probably a very simple issue, but I cannot resolve it.
Thank you very much.
EDIT: this sort does not involve the key itself, but rather a child-element key. i believe that makes this question unique.

Try this:
It will maintain your index associations.
$myArray = array(
'my last row' => array(
'0' => 'ZZZZ',
'1' => 'AAAA'
),
'the first row' => array(
'0' => 'AAAA'
)
);
asort($myArray);
print_r($myArray);
Array ( [the first row] => Array ( [0] => AAAA ) [my last row] => Array ( [0] => ZZZZ [1] => AAAA ) )

Related

Cannot sort array of object by property name

I have this array:
$array = array(
['name' => 'Indor Swimming Pool'],
['name' => 'abracadabra'],
);
I want sort if alphabetically, so I did:
usort($array, function($a, $b)
{
return strcmp($a['name'], $b['name']);
});
but when I dump it:
var_dump($array);
I get:
array(2) {
[0]=>
array(1) {
["name"]=>
string(19) "Indor Swimming Pool"
}
[1]=>
array(1) {
["name"]=>
string(11) "abracadabra"
}
}
this is incorrect, abracadabra should go as first
According to the ASCII table chr I comes first and then comes the a chr
ASCII Table
So here your array is actually getting sorted alphabetically to achieve the desired result you need to sort the array in the descending order
<?php
$data = array(
['name' => 'Indor Swimming Pool'],
['name' => 'abracadabra'],
);
arsort($data);
?>
Output
Array
(
[1] => Array
(
[name] => abracadabra
)
[0] => Array
(
[name] => Indor Swimming Pool
)
)
It works as intended. The reason for this order is that 'a' is actually after 'I' in ASCII.

Count the keys of multi-dimension array php

Maybe the title can not explain my question ,please see my example :
I have an multi-dimension array like this :
Array
(
[0] => Array
(
[name] => 'A'
[ec_dest_name] => 楽天testuser_998
),
[1] => Array
(
[name] => 'A'
[ec_dest_name] => 楽天testuser_998
),
[2] => Array
(
[name] => 'B'
[ec_dest_name] => 楽天testuser_998
),
[3] => Array
(
[name] => 'C'
[ec_dest_name] => 楽天testuser_998
)
)
I want to count the element by key name , it mean that I want to return an array like :
Array ('A' => 2 , 'B'=>1, 'C'=>1)
Any quick way to accomplish that , I could loop array and count but I think it is not a good idea
Thank in advanced
You can use array_count_values & array_column togather -
$counts = array_count_values(array_column($your_array, 'name'));
Output
array(3) {
["A"]=>
int(2)
["B"]=>
int(1)
["C"]=>
int(1)
}
Demo
As Mark Baker suggested for older PHP versions -
$counts = array_count_values(
array_map(function($value) {
return $value['name'];
}, $your_array)
);
You may as well do that with 2 Loops as shown below. You might test this also HERE.
<?php
$arrSections = array();
$arrCounts = array();
$arrMain = array(
array(
'name' => "A",
'ec_dest_name' => "楽天testuser_998",
),
array(
'name' => "A",
'ec_dest_name' => "楽天testuser_998",
),
array(
'name' => "B",
'ec_dest_name' => "楽天testuser_998",
),
array(
'name' => "C",
'ec_dest_name' => "楽天testuser_998",
),
);
// BUNDLE ARRAYS WITH SIMILAR name INTO ONE GROUP
// THUS CREATING A MULTI-DIMENSIONAL ARRAY WHOSE MAIN KEYS CORRESPOND TO
// THE name OF THE MEMBER ARRAYS IN THE GROUP.
foreach($arrMain as $iKey=>$subMain){
$name = $subMain['name'];
if(!array_key_exists($name, $arrSections)) {
$arrSections[$name] = array();
}
$arrSections[$name][] = $subMain;
}
// FETCH THE COUNTS OF EACH GROUP AND MAKE AN ARRAY OUT OF IT...
foreach($arrSections as $k=>$v){
$arrCounts[$k] = count($v);
}
var_dump($arrCounts);
//OUTPUTS::
array (size=3)
'A' => int 2
'B' => int 1
'C' => int 1

PHP: Given a multidimensional array convert it into single dimensional sorted, sort of

Basically, I want to convert the below multidimensional array:
Array
(
[0] => Array
(
[0] => foo
[1] => bar
[2] => hello
)
[1] => Array
(
[0] => world
[1] => love
)
[2] => Array
(
[0] => stack
[1] => overflow
[2] => yep
[3] => man
)
)
Into this:
Array
(
[0] => foo
[1] => world
[2] => stack
[3] => bar
[4] => love
[5] => overflow
[6] => hello
[7] => yep
[8] => man
)
first element from first sub-array
first element from second sub-array, etc
second element from first sub-array
second element from second sub-array, etc...
So I've had a couple beers and I'll try and tighten this up later, but this does the trick for integer indexed arrays:
$result = array();
for($i=0; $c=array_column($array, $i); $i++) {
$result = array_merge($result, $c);
}
print_r($result);
Loop getting an array of columns starting with column 0 and increment the column number.
So long as there are columns, get an array of that column and merge with the result.
There is an often overlooked Iterator that will help you here: The MultipleIterator.
I have created some demo code: https://3v4l.org/beOMV
<?php
$arr = [
0 => [
0 => 'foo',
1 => 'bar',
2 => 'hello',
],
1 => [
0 => 'world',
1 => 'love',
],
2 => [
0 => 'stack',
1 => 'overflow',
2 => 'yep',
3 => 'man',
]
];
$parallelIterator = new MultipleIterator(MultipleIterator::MIT_NEED_ANY|MultipleIterator::MIT_KEYS_NUMERIC);
$parallelIterator->attachIterator(new ArrayIterator($arr[0]));
$parallelIterator->attachIterator(new ArrayIterator($arr[1]));
$parallelIterator->attachIterator(new ArrayIterator($arr[2]));
$result = [];
foreach ($parallelIterator as $values) {
foreach ($values as $value) {
if ($value !== null) {
$result[] = $value;
}
}
}
var_dump($result);
Essentially, iterating over the MultipleIterator will give you an array with all the first entries (and then second and so on) of ALL attached iterators in parallel. By using either MultipleIterator::MIT_NEED_ANY or MultipleIterator::MIT_NEED_ALL you can decide that the loop should stop either when the last iterator has no more elements, or when the first iterator runs out of elements. When you run until the last element of the last iterator, you'll get NULL instead.
When attaching iterators, you can also add a key that will be used in the array when iterating, and have to uses MultipleIterator::MIT_KEYS_ASSOC - I have simply used numeric indices here because the source of the particular array was not interesting.
The result is
array(9) {
[0]=> string(3) "foo"
[1]=> string(5) "world"
[2]=> string(5) "stack"
[3]=> string(3) "bar"
[4]=> string(4) "love"
[5]=> string(8) "overflow"
[6]=> string(5) "hello"
[7]=> string(3) "yep"
[8]=> string(3) "man"
}
Yes, you can iterate over that initial array when attaching the sub arrays to the MultipleIterator if you want:
foreach ($arr as $innerArr) {
$parallelIterator->attachIterator(new ArrayIterator($innerArr));
}

Remove similar objects from array?

I have an array of objects, but I need to remove a similar objects by a few properties from them:
for example:
array(12) {
[0]=>
object(stdClass)#848 (5) {
["variant"]=>
object(stdClass)#849 (4) {
["name"]=>
string(8) "Alex"
}
["age"]=>
int(10)
}
[1]=>
object(stdClass)#851 (5) {
["variant"]=>
object(stdClass)#852 (4) {
["name"]=>
string(8) "Alex"
}
["age"]=>
int(10)
}
How to make a one object in array for this ( if for example I need to compare only by a name property? )
Still have an issue with it.
Updated
I've create a new array of objects:
$objects = array(
(object)array('name'=>'Stiven','age'=>25,'variant'=>(object)array('surname'=>'Sigal')),
(object)array('name'=>'Michael','age'=>30,'variant'=>(object)array('surname'=>'Jackson')),
(object)array('name'=>'Brad','age'=>35,'variant'=>(object)array('surname'=>'Pit')),
(object)array('name'=>'Jolie','age'=>35,'variant'=>(object)array('surname'=>'Pit')),
);
echo "<pre>";
print_r($objects);
So what I need to do is to compare an object properties (variant->surnames and ages), if two objects has a similar age and variant->surname we need to remove the one of these objects.
A half of solution is:
$tmp = array();
foreach ($objects as $item=>$object)
{
$tmp[$object->variant->surname][$object->age] = $object;
}
print_r($tmp);
Unfortunatelly I need an old-style array of objects.
I've found an example.
<?php
$a = array (
0 => array ( 'value' => 'America', ),
1 => array ( 'value' => 'England', ),
2 => array ( 'value' => 'Australia', ),
3 => array ( 'value' => 'America', ),
4 => array ( 'value' => 'England', ),
5 => array ( 'value' => 'Canada', ),
);
$tmp = array ();
foreach ($a as $row)
if (!in_array($row,$tmp)) array_push($tmp,$row);
print_r ($tmp);
?>
Quoted from here

Recreate Multidimensional Array in PHP

This is pretty basic, but my question is:
Given an array:
$a = array(
0 => array('Rate'=> array('type_id'=>1, 'name' => 'Rate_1', 'type'=>'day','value'=>10)),
1 => array('Rate'=> array('type_id'=>1, 'name' => 'Rate_2', 'type'=>'night','value'=>8)),
2 => array('Rate'=> array('type_id'=>2, 'name' => 'Rate_3', 'type'=>'day','value'=>7)),
3 => array('Rate'=> array('type_id'=>2, 'name' => 'Rate_4', 'type'=>'nigh','value'=>16)),
4 => array('Rate'=> array('type_id'=>3, 'name' => 'Rate_5', 'type'=>'day','value'=>10))
);
What is the most efficient way to change it so we have something like:
$new_array = array(
[type_id] => array(
[type] => array(
[value]
)
)
)
);
In other words, I would like to strip some data (the name, which I don't need) and reorganise the dimensions of the array. In the end I would have an array which I would be able to access the values by $new_array['type_id']['type']['value'].
Not entirely sure if this is exactly what you want, but with this you can access the values by saying
echo $new[TYPE_ID][DAY_OR_NIGHT];
$new = array();
foreach($a AS $b){
$c = $b['Rate'];
$new[$c['type_id']][$c['type']] = $c['value'];
}
Using print_r on $new would give you:
Array
(
[1] => Array
(
[day] => 10
[night] => 8
)
[2] => Array
(
[day] => 7
[night] => 16
)
[3] => Array
(
[day] => 10
)
)
Since php 5.3.0, array_reduce() allows using an array as the initial value, given your initial array $a, you can use the following code
function my_reducer ($result, $item) {
$result[$item['Rate']['type_id']][$item['Rate']['type']] = $item['Rate']['value'];
return $result;
}
$assoc_arr = array_reduce($a, 'my_reducer', array());
var_dump($assoc_arr);
This returns
array(3) { [1]=> array(2) {
["day"]=>
int(10)
["night"]=>
int(8) } [2]=> array(2) {
["day"]=>
int(7)
["nigh"]=>
int(16) } [3]=> array(1) {
["day"]=>
int(10) } }

Categories