PHP Sort Mega-Array by Value - php

I am looking for some advices how could I sort this kind of Array by 'variant_name' key.
Because Array is really huge I minified it to the looking result state.
...
$filter[2413][1][81][sub_id] = 1;
$filter[2413][1][81][variant_id] = 81;
$filter[2413][1][81][variant_name] = 'Banana';
$filter[2413][2][87][sub_id] = 2;
$filter[2413][2][87][variant_id] = 87;
$filter[2413][2][87][variant_name] = 'Apple';
$filter[2413][3][32][sub_id] = 3;
$filter[2413][3][32][variant_id] = 32;
$filter[2413][3][32][variant_name] = 'Carrot';
...
Keys $filter[x][x][x] are not sequential.
I have tried the sort function I used before but it doesn't work with this kind of Array:
function array_sort_by_column(&$arr, $col, $dir = SORT_ASC) {
$sort_col = array();
foreach ($arr as $key=> $row) {
$sort_col[$key] = $row[$col];
}
array_multisort($sort_col, $dir, $arr);
}
array_sort_by_column($filter[][][], 'variant_name');
My target is modify array by sorting 'variant_name' to 'Apple', 'Banana', 'Carrot' accordingly keeping the array structure.

It's a working code tested from given examples.
Note that my codes still can be optimized, etc. Just take it as my advice.
TL;DR = Use usort().
function mySort($a,$b)
{
$av = "";
$bv = "";
foreach($a as $ak)
$av = $ak['variant_name'];
foreach($b as $bk)
$bv = $bk['variant_name'];
if($av[0] < $bv[0])
return false;
else return true;
}
How to use it? You have to specify which first level array to sort.
usort($filter['2413'],"mySort");
Then the result I got is:
Array
(
[2413] => Array
(
[0] => Array
(
[87] => Array
(
[sub_id] => 2
[variant_id] => 87
[variant_name] => Apple
)
)
[1] => Array
(
[81] => Array
(
[sub_id] => 1
[variant_id] => 81
[variant_name] => Banana
)
)
[2] => Array
(
[32] => Array
(
[sub_id] => 3
[variant_id] => 32
[variant_name] => Carrot
)
)
)
)

Related

php making an assoc array in a for loop doesn't set the key [duplicate]

I've been looking on google for the answer but can't seem to find something fool-proof and cant really afford to mess this up (going live into a production site).
What I have is an advanced search with 20+ filters, which returns an array including an ID and a Distance. What I need to do is shuffle these results to display in a random order every time. The array I have that comes out at the moment is:
Array (
[0] => Array ( [id] => 1 [distance] => 1.95124994507577 )
[1] => Array ( [id] => 13 [distance] => 4.75358968511882 )
[2] => Array ( [id] => 7 [distance] => 33.2223233233323 )
[3] => Array ( [id] => 21 [distance] => 18.2155453552336 )
[4] => Array ( [id] => 102 [distance] = 221.2212587899658 )
)
What I need to be able to do is randomise or order of these every time but maintain the id and distance pairs, i.e.:
Array (
[4] => Array ( [id] => 102 [distance] = 221.2212587899658 )
[1] => Array ( [id] => 13 [distance] => 4.75358968511882 )
[3] => Array ( [id] => 21 [distance] => 18.2155453552336 )
[2] => Array ( [id] => 7 [distance] => 33.2223233233323 )
[0] => Array ( [id] => 1 [distance] => 1.95124994507577 )
)
Thanks :)
The first user post under the shuffle documentation:
Shuffle associative and
non-associative array while preserving
key, value pairs. Also returns the
shuffled array instead of shuffling it
in place.
function shuffle_assoc($list) {
if (!is_array($list)) return $list;
$keys = array_keys($list);
shuffle($keys);
$random = array();
foreach ($keys as $key) {
$random[$key] = $list[$key];
}
return $random;
}
Test case:
$arr = array();
$arr[] = array('id' => 5, 'foo' => 'hello');
$arr[] = array('id' => 7, 'foo' => 'byebye');
$arr[] = array('id' => 9, 'foo' => 'foo');
print_r(shuffle_assoc($arr));
print_r(shuffle_assoc($arr));
print_r(shuffle_assoc($arr));
As of 5.3.0 you could do:
uksort($array, function() { return rand() > rand(); });
Take a look to this function here :
$foo = array('A','B','C');
function shuffle_with_keys(&$array) {
/* Auxiliary array to hold the new order */
$aux = array();
/* We work with an array of the keys */
$keys = array_keys($array);
/* We shuffle the keys */`enter code here`
shuffle($keys);
/* We iterate thru' the new order of the keys */
foreach($keys as $key) {
/* We insert the key, value pair in its new order */
$aux[$key] = $array[$key];
/* We remove the element from the old array to save memory */
unset($array[$key]);
}
/* The auxiliary array with the new order overwrites the old variable */
$array = $aux;
}
shuffle_with_keys($foo);
var_dump($foo);
Original post here :
http://us3.php.net/manual/en/function.shuffle.php#83007
function shuffle_assoc($array)
{
$keys = array_keys($array);
shuffle($keys);
return array_merge(array_flip($keys), $array);
}
I was having a hard time with most of the answers provided - so I created this little snippet that took my arrays and randomized them while maintaining their keys:
function assoc_array_shuffle($array)
{
$orig = array_flip($array);
shuffle($array);
foreach($array AS $key=>$n)
{
$data[$n] = $orig[$n];
}
return array_flip($data);
}
Charles Iliya Krempeaux has a nice writeup on the issue and a function that worked really well for me:
function shuffle_assoc($array)
{
// Initialize
$shuffled_array = array();
// Get array's keys and shuffle them.
$shuffled_keys = array_keys($array);
shuffle($shuffled_keys);
// Create same array, but in shuffled order.
foreach ( $shuffled_keys AS $shuffled_key ) {
$shuffled_array[ $shuffled_key ] = $array[ $shuffled_key ];
} // foreach
// Return
return $shuffled_array;
}
Try using the fisher-yates algorithm from here:
function shuffle_me($shuffle_me) {
$randomized_keys = array_rand($shuffle_me, count($shuffle_me));
foreach($randomized_keys as $current_key) {
$shuffled_me[$current_key] = $shuffle_me[$current_key];
}
return $shuffled_me;
}
I had to implement something similar to this for my undergraduate senior thesis, and it works very well.
Answer using shuffle always return the same order. Here is one using random_int() where the order is different each time it is used:
function shuffle_assoc($array)
{
while (count($array)) {
$keys = array_keys($array);
$index = $keys[random_int(0, count($keys)-1)];
$array_rand[$index] = $array[$index];
unset($array[$index]);
}
return $array_rand;
}
$testArray = array('a' => 'apple', 'b' => 'ball', 'c' => 'cat', 'd' => 'dog');
$keys = array_keys($testArray); //Get the Keys of the array -> a, b, c, d
shuffle($keys); //Shuffle The keys array -> d, a, c, b
$shuffledArray = array();
foreach($keys as $key) {
$shuffledArray[$key] = $testArray[$key]; //Get the original array using keys from shuffled array
}
print_r($shuffledArray);
/*
Array
(
[d] => dog
[a] => apple
[c] => cat
[b] => ball
)
*/
I tried the most vote solution didn't popular shuffle list. This is the change I made to make it work.
I want my array key starting from 1.
$list = array_combine(range(1,10),range(100,110));
$shuffle_list = shuffle_assoc($list);
function shuffle_assoc($list)
{
if (!is_array($list)) return $list;
$keys = array_keys($list);
shuffle($list);
$random = array();
foreach ($keys as $k => $key) {
$random[$key] = $list[$k];
}
return $random;
}

Need some help making a php search tree

Im making a tree to store words and an associated number array in php. I need it to look something like this:
Words: apple, ant
[a] => Array
(
[p] => Array
(
[p] => Array
(
[l] => Array
(
[e] => Array
(
[0] => Array
(
[0] => 0
[1] => 0
[2] => 1
[3] => 2
[4] => 3
[5] => 4
)
)
)
)
)
[n] => Array
(
[t] => Array
(
[0] => Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 0
[4] => 0
[5] => 4
)
)
)
)
Of course apple and ant need to share the same [a] index. Im close, but I cant figure out how to properly keep track of the tree index so 'apple' gets into the tree fine but 'ant' is inserted as 'nt'. Heres my code at the moment:
private function insertWordsIntoTree()
{
foreach ($this->words as $word)
{
$characters = preg_replace('/[0-9]+/', '', $words);
$points = $this->getPoints($word);
$this->tree = $this->buildTree($characters, $points, $this->tree);
}
print_r($this->tree);
}
private function buildTree($characters, array $points, array $tree)
{
for ($i = 0; $i < strlen($characters); $i++)
{
$character = $characters[$i];
$remaining_characters = substr($characters, $i + 1);
if (strlen($characters) === 1)
{
$child = [];
$child[$character] = [$points];
return $child;
}
elseif (!isset($tree[$character]))
{
$tree[$character] = $this->buildTree($remaining_characters, $points, []);;
break;
}
else
{
$this->buildTree($remaining_characters, $points, $tree[$character]);
}
}
return $tree;
}
Im pretty sure the problem is at the else statement...I dont think Im keeping track of the current tree index properly. Any help would be much appreciated.
Here's a simple approach that passes the recursion off to php:
$tree = array();
foreach($words as $word) {
$characters = array_reverse(str_split($word));
$temp = array();
foreach($characters as $index => $character) {
if($index == 0) {
$temp[] = getPoints($word);
}
$temp = array(
$character => $temp
);
}
$tree = array_merge_recursive($tree, $temp);
}

Associative index array to associative associative array

Problem
I have an array which is returned from PHPExcel via the following
<?php
require_once 'PHPExcel/Classes/PHPExcel/IOFactory.php';
$excelFile = "excel/1240.xlsx";
$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objPHPExcel = $objReader->load($excelFile);
foreach ($objPHPExcel->getWorksheetIterator() as $worksheet) {
$arrayData[$worksheet->getTitle()] = $worksheet->toArray();
}
print_r($arrayData);
?>
This returns:
Array
(
[Films] => Array
(
[0] => Array
(
[0] => Name
[1] => Rating
)
[1] => Array
(
[0] => Shawshank Redemption
[1] => 39
)
[2] => Array
(
[0] => A Clockwork Orange
[1] => 39
)
)
[Games] => Array
(
[0] => Array
(
[0] => Name
[1] => Rating
)
[1] => Array
(
[0] => F.E.A.R
[1] => 4
)
[2] => Array
(
[0] => World of Warcraft
[1] => 6
)
)
)
What I would like to have is
Array
(
[Films] => Array
(
[0] => Array
(
[Name] => Shawshank Redemption
[Rating] => 39
)
[1] => Array
(
[Name] => A Clockwork Orange
[Rating] => 39
)
)
[Games] => Array
(
[0] => Array
(
[Name] => F.E.A.R
[Rating] => 4
)
[1] => Array
(
[Name] => World of Warcraft
[Rating] => 6
)
)
)
The arrays names (Films, Games) are taken from the sheet name so the amount can be variable. The first sub-array will always contain the key names e.g. Films[0] and Games[0] and the amount of these can be varible. I (think I) know I will need to do something like below but I'm at a loss.
foreach ($arrayData as $value) {
foreach ($value as $rowKey => $rowValue) {
for ($i=0; $i <count($value) ; $i++) {
# code to add NAME[n] as keys
}
}
}
I have searched extensively here and else where if it is a duplicate I will remove it.
Thanks for any input
Try
$result= array();
foreach($arr as $key=>$value){
$keys = array_slice($value,0,1);
$values = array_slice($value,1);
foreach($values as $val){
$result[$key][] = array_combine($keys[0],$val);
}
}
See demo here
You may use nested array_map calls. Somehow like this:
$result = array_map(
function ($subarr) {
$names = array_shift($subarr);
return array_map(
function ($el) use ($names) {
return array_combine($names, $el);
},
$subarr
);
},
$array
);
Demo
Something like this should work:
$newArray = array();
foreach ($arrayData as $section => $list) {
$newArray[$section] = array();
$count = count($list);
for ($x = 1; $x < $count; $x++) {
$newArray[$section][] = array_combine($list[0], $list[$x]);
}
}
unset($arrayData, $section, $x);
Demo: http://ideone.com/ZmnFMM
Probably a little late answer, but it looks more like your tried solution
//Films,Games // Row Data
foreach ($arrayData as $type => $value)
{
$key1 = $value[0][0]; // Get the Name Key
$key2 = $value[0][1]; // Get the Rating Key
$count = count($value) - 1;
for ($i = 0; $i < $count; $i++)
{
/* Get the values from the i+1 row and put it in the ith row, with a set key */
$arrayData[$type][$i] = array(
$key1 => $value[$i + 1][0],
$key2 => $value[$i + 1][1],
);
}
unset($arrayData[$type][$count]); // Unset the last row since this will be repeated data
}
I think this will do:
foreach($arrayData as $key => $array){
for($i=0; $i<count($array[0]); $i++){
$indexes[$i]=$array[0][$i];
}
for($i=1; $i<count($array); $i++){
for($j=0; $j<count($array[$i]); $j++){
$temp_array[$indexes[$j]]=$array[$i][$j];
}
$new_array[$key][]=$temp_array;
}
}
print_r($new_array);
EDIT: tested and updated the code, works...

help needed restructuring a php array

I was wondering if anyone could help me restructure a predefined php array. The output of my current array is:
Array
(
[71-ctns] => 1
[71-units] => 1
[308-units] => 1
[305-ctns] => 1
[306-units] => 2
)
And I would like it to look like:
Array
(
[71] => Array
(
[ctns] => 1
[units] => 1
)
[308] => Array
(
[units] => 1
)
[305] => Array
(
[ctns] => 1
)
[306] => Array
(
[units] => 2
)
)
Is this possible?
This should do it
$merged = array();
foreach($a as $k=>$v){
$t = explode('-',$k);
$id = intval($t[0]);
if(!array_key_exists($id, $merged))
$merged[$id] = array();
$merged[$id][$t[1]] = $v;
}
EDIT:
Sorry you should use explode instead of split.
Yes, but you need to loop (note: array_map can also work, but this example is more explicit):
$fin = array();
foreach( $complex as $item => $val )
{
$pieces = explode('-', $item);
$fin[$pieces[0]] = isset($fin[$pieces[0]])?:array();
$fin[$pieces[0]][$pieces[1]] = $val;
}
Find below code to restructure a predefined php array
<?php
$newArray=array();
$result = array("71-ctns"=>1,"71-units"=>1,"308-ctns"=>1,"308-units"=>1,"305-units"=>1,"306-units"=>2);
if(is_array($result) && count($result)>0) {
foreach($result as $key=>$val) {
$getKeyArray = explode("-",$key);
$newArray[$getKeyArray[0]][$getKeyArray[1]] =$val;
}
}
print"<pre>";
print_r($newArray);
?>

PHP Random Shuffle Array Maintaining Key => Value

I've been looking on google for the answer but can't seem to find something fool-proof and cant really afford to mess this up (going live into a production site).
What I have is an advanced search with 20+ filters, which returns an array including an ID and a Distance. What I need to do is shuffle these results to display in a random order every time. The array I have that comes out at the moment is:
Array (
[0] => Array ( [id] => 1 [distance] => 1.95124994507577 )
[1] => Array ( [id] => 13 [distance] => 4.75358968511882 )
[2] => Array ( [id] => 7 [distance] => 33.2223233233323 )
[3] => Array ( [id] => 21 [distance] => 18.2155453552336 )
[4] => Array ( [id] => 102 [distance] = 221.2212587899658 )
)
What I need to be able to do is randomise or order of these every time but maintain the id and distance pairs, i.e.:
Array (
[4] => Array ( [id] => 102 [distance] = 221.2212587899658 )
[1] => Array ( [id] => 13 [distance] => 4.75358968511882 )
[3] => Array ( [id] => 21 [distance] => 18.2155453552336 )
[2] => Array ( [id] => 7 [distance] => 33.2223233233323 )
[0] => Array ( [id] => 1 [distance] => 1.95124994507577 )
)
Thanks :)
The first user post under the shuffle documentation:
Shuffle associative and
non-associative array while preserving
key, value pairs. Also returns the
shuffled array instead of shuffling it
in place.
function shuffle_assoc($list) {
if (!is_array($list)) return $list;
$keys = array_keys($list);
shuffle($keys);
$random = array();
foreach ($keys as $key) {
$random[$key] = $list[$key];
}
return $random;
}
Test case:
$arr = array();
$arr[] = array('id' => 5, 'foo' => 'hello');
$arr[] = array('id' => 7, 'foo' => 'byebye');
$arr[] = array('id' => 9, 'foo' => 'foo');
print_r(shuffle_assoc($arr));
print_r(shuffle_assoc($arr));
print_r(shuffle_assoc($arr));
As of 5.3.0 you could do:
uksort($array, function() { return rand() > rand(); });
Take a look to this function here :
$foo = array('A','B','C');
function shuffle_with_keys(&$array) {
/* Auxiliary array to hold the new order */
$aux = array();
/* We work with an array of the keys */
$keys = array_keys($array);
/* We shuffle the keys */`enter code here`
shuffle($keys);
/* We iterate thru' the new order of the keys */
foreach($keys as $key) {
/* We insert the key, value pair in its new order */
$aux[$key] = $array[$key];
/* We remove the element from the old array to save memory */
unset($array[$key]);
}
/* The auxiliary array with the new order overwrites the old variable */
$array = $aux;
}
shuffle_with_keys($foo);
var_dump($foo);
Original post here :
http://us3.php.net/manual/en/function.shuffle.php#83007
function shuffle_assoc($array)
{
$keys = array_keys($array);
shuffle($keys);
return array_merge(array_flip($keys), $array);
}
I was having a hard time with most of the answers provided - so I created this little snippet that took my arrays and randomized them while maintaining their keys:
function assoc_array_shuffle($array)
{
$orig = array_flip($array);
shuffle($array);
foreach($array AS $key=>$n)
{
$data[$n] = $orig[$n];
}
return array_flip($data);
}
Charles Iliya Krempeaux has a nice writeup on the issue and a function that worked really well for me:
function shuffle_assoc($array)
{
// Initialize
$shuffled_array = array();
// Get array's keys and shuffle them.
$shuffled_keys = array_keys($array);
shuffle($shuffled_keys);
// Create same array, but in shuffled order.
foreach ( $shuffled_keys AS $shuffled_key ) {
$shuffled_array[ $shuffled_key ] = $array[ $shuffled_key ];
} // foreach
// Return
return $shuffled_array;
}
Try using the fisher-yates algorithm from here:
function shuffle_me($shuffle_me) {
$randomized_keys = array_rand($shuffle_me, count($shuffle_me));
foreach($randomized_keys as $current_key) {
$shuffled_me[$current_key] = $shuffle_me[$current_key];
}
return $shuffled_me;
}
I had to implement something similar to this for my undergraduate senior thesis, and it works very well.
Answer using shuffle always return the same order. Here is one using random_int() where the order is different each time it is used:
function shuffle_assoc($array)
{
while (count($array)) {
$keys = array_keys($array);
$index = $keys[random_int(0, count($keys)-1)];
$array_rand[$index] = $array[$index];
unset($array[$index]);
}
return $array_rand;
}
$testArray = array('a' => 'apple', 'b' => 'ball', 'c' => 'cat', 'd' => 'dog');
$keys = array_keys($testArray); //Get the Keys of the array -> a, b, c, d
shuffle($keys); //Shuffle The keys array -> d, a, c, b
$shuffledArray = array();
foreach($keys as $key) {
$shuffledArray[$key] = $testArray[$key]; //Get the original array using keys from shuffled array
}
print_r($shuffledArray);
/*
Array
(
[d] => dog
[a] => apple
[c] => cat
[b] => ball
)
*/
I tried the most vote solution didn't popular shuffle list. This is the change I made to make it work.
I want my array key starting from 1.
$list = array_combine(range(1,10),range(100,110));
$shuffle_list = shuffle_assoc($list);
function shuffle_assoc($list)
{
if (!is_array($list)) return $list;
$keys = array_keys($list);
shuffle($list);
$random = array();
foreach ($keys as $k => $key) {
$random[$key] = $list[$k];
}
return $random;
}

Categories