This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Sort multidimensional array by multiple keys
I am trying to find some way how to sort array by key name, but nothing worked so far. The tricky part for me is to sort array by grouping 3 keys. I have this array.
[0] => Array
(
[id] => 8
[zbo_data] => blah
)
[1] => Array
(
[id] => 6
[szn_data] => blah
)
[2] => Array
(
[id] => 5
[gcz_data] => blah
)
[3] => Array
(
[id] => 3
[gcz_data] => blah
)
[4] => Array
(
[id] => 2
[zbo_data] => blah
)
[5] => Array
(
[id] => 1
[szn_data] => blah
)
And I need to sort it by group of 3 in this order: szn_data, zbo_data, gcz_data but I also need to keep the order of [id] (basically primary order by szn_data, zbo_data, gcz_data, secondary [id]). Is there a solution? Or should I construct array differently to be able to sort it? I am trying to figure this out for over 6 hours. Any help is much appreciated.
My desired output is:
[0] => Array
(
[id] => 6
[szn_data] => blah
)
[1] => Array
(
[id] => 8
[zbo_data] => blah
)
[2] => Array
(
[id] => 5
[gcz_data] => blah
)
[3] => Array
(
[id] => 1
[szn_data] => blah
)
[4] => Array
(
[id] => 2
[zbo_data] => blah
)
[5] => Array
(
[id] => 3
[gcz_data] => blah
)
Use usort and implement your comparison function as you wish. For example:
$result = usort($arr, function($a,$b) {
$keys = array('szn_data', 'zbo_data', 'gcz_data');
foreach ($keys as $key) {
// make sure to add here handling of missing keys
$diff = strcmp($b[$key], $a[$key]);
if ($diff!=0) {
return $diff;
}
}
return $b['id'] - $a['id'];
});
Or like this, for any order from max to the min listed in one array
$arr = array (
array(
'id' => 8,
'zbo_data' => 'blah'
),
array(
'id' => 6,
'szn_data' => 'blah'
),
array(
'id' => 5,
'gcz_data' => 'blah'
),
array(
'id' => 3,
'gcz_data' => 'blah'
),
array(
'id' => 2,
'zbo_data' => 'blah'
),
array(
'id' => 1,
'szn_data' => 'blah'
)
);
usort($arr, "my_func");
var_dump($arr);
function my_func($a, $b)
{
$vars = array('szn_data', 'zbo_data', 'gcz_data'); // order of the keys
$id1 = $a['id']; $id2 = $b['id']; unset($a['id'], $b['id']);
$index1 = array_search(key($a), $vars);
$index2 = array_search(key($b), $vars);
if ($index1 == $index2) {
if ($id1 == $id2) return 0;
return ($id1 < $id2) ? 1 : -1;
}
return ($index1 < $index2) ? -1 : 1;
}
ps:
basically primary order by szn_data, zbo_data, gcz_data, secondary
[id]
It does not correspond to your desired output. Secondary means comparison of id when other keys are the same.
ps: Updated - this code is NOT nice or perfect, but it will give you what you need
$vars = array('szn_data', 'zbo_data', 'gcz_data');
$arr = array (
array(
'id' => 8,
'zbo_data' => 'blah'
),
array(
'id' => 6,
'szn_data' => 'blah'
),
array(
'id' => 5,
'gcz_data' => 'blah'
),
array(
'id' => 3,
'gcz_data' => 'blah'
),
array(
'id' => 2,
'zbo_data' => 'blah'
),
array(
'id' => 1,
'szn_data' => 'blah'
)
);
$temp = array();
$cnt = count($arr);
foreach($arr as $item)
{
foreach($vars as $v)
{
if (isset($item[$v])) { $temp[$v][$item['id']] = $item; break; }
}
}
// sort by id
foreach($vars as $v)
{
krsort($temp[$v]);
$temp[$v] = array_values($temp[$v]);
}
$arr = array(); $i = 0; $j = 0;
$completed = false;
do {
foreach($vars as $v)
{
if ($i++>=$cnt) { $completed = true; break; }
if (isset($temp[$v][$j])) $arr[] = $temp[$v][$j];
}
$j++;
} while (!$completed);
// output
var_dump($arr)
Related
i have data array, and this my array
Array
(
[0] => Array
(
[id] => 9,5
[item] => Item A, Item B
)
[1] => Array
(
[id] => 3
[item] => Item C
)
)
in array 0 there are two ID which I separated using a comma, I want to extract the data into a new array, how to solve this?
so the output is like this
Array
(
[0] => Array
(
[id] => 9
[item] => Item A
)
[1] => Array
(
[id] => 3
[item] => Item C
)
[2] => Array //new array
(
[id] => 5
[item] => Item B
)
)
this my code
$arr=array();
foreach($myarray as $val){
$arr[] = array(
'id' => $val['id'],
'item' => $val['item'],
);
}
echo '<pre>', print_r($arr);
$arr = [
array(
'id' => '9,5',
'item' => 'Item A, Item B'
),
array(
'id' => 3,
'item' => 'Item C'
)
];
$newArr = array_reduce($arr, function($tmp, $ele){
$arrIds = explode(',', $ele['id']);
$arrItems = explode(',', $ele['item']);
forEach($arrIds as $key => $arrId) {
$tmp[] = array('id' => $arrId, 'item' => $arrItems[$key]);
}
return $tmp;
});
The code down below should do the job. But I didn't understand why you didn't create those items seperately in the first place.
foreach ($arr as $i => $data) {
if (!str_contains($data['id'], ',')) continue;
$items = explode(',', $data['item']);
foreach(explode(',', $data['id']) as $i => $id) {
$new = ['id' => $ids[$i], 'item' => $items[$i]];
if ($i) $arr[] = $new;
else $arr[$i] = $new;
}
}
I'm trying to read a session variable, create arrays and concatenate them :
Session variable sample:
Array
(
[0] => Array
(
[idArticle] => 224
[ntypeArticle] => 1
)
[1] => Array
(
[idArticle] => 556
[ntypeArticle] => 2
)
[2] => Array
(
[idArticle] => 312
[ntypeArticle] => 1
)
)
I need to read this arrays one by one and create arrays by "ntypeArticle".
If ntypeArticle=1, create array1
If ntypeArticle=2, create array2
My code :
$type1 = array();
$type2= array();
$typeAll = array();
foreach($_SESSION['cart'] as $item)
{
if ($item['ntypeArticle'] == 1) {
$type1= array ( "Type" => '1', );
} else {
$type2= array ( "Type" => '2', );
}
array_push($typeAll , $type1 , $type2);
}
But this creates empty arrays.
Wanted output :
Array
(
[0] => Array
(
[type] => 1
)
[1] => Array
(
[type] => 2
)
[2] => Array
(
[type] => 1
)
)
All you need is this simple thing:
$out = [];
foreach($_SESSION['cart'] as $k => $item)
{
$out[$k] = ['Type' => $item['ntypeArticle']];
}
Now if you output $out variable you get what you need.
Try This
$newOp1 = array()
$newOp2 = array()
foreach($_SESSION['cart'] as $item){
if($item["ntypeArticle"] == 1){
$newOp1[]['type'] = $item["ntypeArticle"]
}else{
$newOp2[]['type'] = $item["ntypeArticle"]
}
}
print_r($newOp1);
print_r($newOp2);
Basing on information you provided, all you want to do is to extract nTypeArticle as type element. That's all.
//array from your example
$inputArray = array(
array(
'idArticle' => 224,
'nTypeArticle' => 1
),
array(
'idArticle' => 556,
'nTypeArticle' => 2
),
array(
'idArticle' => 312,
'nTypeArticle' => 1
),
);
$outputArray = array_map(function($inputElement) {
return array('type' => $inputElement['nTypeArticle']);
}, $inputArray);
var_dump($outputArray);
//Output (the same as yours):
//array (size=3)
// 0 =>
// array (size=1)
// 'type' => int 1
// 1 =>
// array (size=1)
// 'type' => int 2
// 2 =>
// array (size=1)
// 'type' => int 1
$output = new array();
$input = array(
array(
"idArticle" => 224,
"nTypeArticle" => 1
),
array(
"idArticle" => 556,
"nTypeArticle" => 2
),
array(
"idArticle" => 312,
"nTypeArticle" => 1
)
);
foreach($input as $article) {
array_push($output, new array("type"=>$article["nTypeArticle"]));
}
print_r($output);
This gives you the thing you asked for.
(Code has been not tested)
I have two arrays, examples of the structures below:
Array #1 -- keys are stored in the first index of the array as the corresponding value.
Array(
[0] => Array(
[0] => name
[1] => time
),
[1] => Array(
[0] => Bob
[1] => 20
),
[2] => Array(
[0] => Jack
[1] => 25
)
)
Array #2 -- each array has a numbered key and named key with the corresponding value being the same
Array(
[0] => Array(
[name] => Bob
[0] => Bob
[time] => 20
[1] => 20
),
[1] => Array(
[name] => Test
[0] => Test
[time] => 40
[1] => 40
)
)
Attempt:
foreach($arr as $record) {
if(!in_array($record['name'], $names))
$names[] = $record['name'];
}
foreach($csv as $rec) {
if(!in_array($rec[0], $names))
$names[] = $rec[0];
}
How can I combine these arrays, and weed out and duplicates based on the value of the name?
Try the code below, i added commands between the code.
//Array 1
$array1 = Array(
0 => Array(
0 => "Bob",
1 => 20,
),
1 => Array(
0 => "Jack",
1 => 25,
));
//Array 2
$array2 = Array(
0 => Array(
"name" => "Bob",
0 => "Bob",
"time" => 20,
1 => 20,
),
1 => Array(
"name" => "Test",
0 => "Test",
"time" => 40,
1 => 40,
));
//Function to search if the value already exists
function inArray($array, $search)
{
foreach($array as $key=>$subArray)
{
if(in_array($search, $subArray))
{
return true;
}
}
return false;
}
$newArray = array();
//Loop over array1 length + array2 length
for($i = 0 ; $i < (count($array1) + count($array2)) ; $i++)
{
//Choose the array based on the counter ($i)
if($i < count($array1))
{
$data = $array1;
$arrayIndex = $i;
}
else
{
$data = $array2;
$arrayIndex = $i - count($array1);
}
//Check if array value exists
if(!inArray($newArray,$data[$arrayIndex][0]))
{
//Add if it doesn't exists with the keys 'name' and 'time'
$newArray[] = array('name' => $data[$arrayIndex][0], 'time'=> $data[$arrayIndex][1]);
}
}
print_r($newArray);
The output will be:
Array
(
[0] => Array
(
[name] => Bob
[time] => 20
)
[1] => Array
(
[name] => Jack
[time] => 25
)
[2] => Array
(
[name] => Test
[time] => 40
)
)
Just need a little help here about arrays. Because I am trying to create a code that when you click it it will replace a certain array values.
In the base array suppose that we have this array:
Array(
[0] => Array(
[id] => 1,
[name] => xyz
),
[1] => Array(
[id] => 4,
[name] => fsa
),
)
And in my new array I have something like this
Array(
[id] => 4,
[name] => pop
)
I have a validation like this: In the base array I put this array in $base_array and in my new array I have $update_array
$get_updated_array_id = $update_array[id];
for($x = 0; $x <= sizeof($base_array); $x++){
$target = $base_array[$x]['id'];
if($get_updated_array_id == $target){
//should be replace the array value ID '4'
}
}
So the final result should be:
Array(
[0] => Array(
[id] => 1,
[name] => xyz
),
[1] => Array(
[id] => 4,
[name] => pop
),
)
Any idea how can I do that? Thanks
<?php
$array = array(
array('id' => 2,'name' => 'T'),
array('id' => 4,'name' => 'S')
);
$replace = array('id' => 4,'name' => 'New name');
foreach ($array as $key => &$value) {
if($value['id'] == $replace['id'] ) {
$value = $replace;
}
}
print_r($array);
$new_array = array(
[id] => 4,
[name] => pop
);
$get_updated_array_id = $update_array[id];
for($x = 0; $x <= sizeof($base_array); $x++){
$target = $base_array[$x]['id'];
if($get_updated_array_id == $target){
$base_array[$x] = $new_array;
}
}
//PHP >= 5.3
array_walk($base_array, function (& $target) use ($update_array) {
if ($target['id'] == $update_array['id']) {
$target = $update_array;
}
});
I have an php array like below:
Array (
[0] => Array ( [value] => 5 [label] => Akon )
[1] => Array ( [value] => 6 [label] => Angel )
[2] => Array ( [value] => 7 [label] => Britny )
[3] => Array ( [value] => 9 [label] => Mark Anthony )
[4] => Array ( [value] => 8 [label] => Michel )
[5] => Array ( [value] => 4 [label] => Shaggy )
[6] => Array ( [value] => 3 [label] => Smith )
)
I need this array sort by specific letter. For example, if I sort by this "M" letter array should look like below.
Array (
[3] => Array ( [value] => 9 [label] => Mark Anthony )
[4] => Array ( [value] => 8 [label] => Michel )
[6] => Array ( [value] => 3 [label] => Smith )
[0] => Array ( [value] => 5 [label] => Akon )
[1] => Array ( [value] => 6 [label] => Angel )
[2] => Array ( [value] => 7 [label] => Britny )
[5] => Array ( [value] => 4 [label] => Shaggy )
)
The begging letter should comes to first of array.(here begin with m)
I greatly appreciated your any kind of help. Thank you very much...
Your comparison logic is going to be like this:
if two strings A and B start with the same letter, compare them as usual
if A starts with 'M', A wins
if B starts with 'M', B wins
otherwise, compare as usual
in code
$strings = array('Foo', 'Moo', 'Xuux', 'Me', 'Blah', 'Ma');
$letter = 'M';
usort($strings, function($a, $b) use($letter) {
if($a[0] != $b[0]) {
if($a[0] == $letter) return -1;
if($b[0] == $letter) return +1;
}
return strcmp($a, $b);
});
print_r($strings);
class Cmp {
public $letter;
function __construct( $letter ) { $this->letter = $letter; }
function doCmp( $a, $b ) {
if( $a['label'][0] == $this->letter ) {
if( $b['label'][0] != $this->letter ) return -1;
} else {
if( $b['label'][0] == $this->letter ) return 1;
}
return $a['label'] > $b['label'] ? 1 : -1;
}
}
usort( $arr, array( new Cmp( 'M' ), 'doCmp' ) );
$strings = array (
array ( 'value' => 5, 'label' => 'Akon' ),
array ( 'value' => 6, 'label' => 'Angel' ),
array ( 'value' => 7, 'label' => 'Britny' ),
array ( 'value' => 9, 'label' => 'Mark Anthony' ) ,
array ( 'value' => 8, 'label' => 'Michel' ) ,
array ( 'value' => 4, 'label' => 'Shaggy' ) ,
array ( 'value' => 3, 'label' => 'Smith' )
) ;
var_dump($strings);
$letter = 'm';
usort ($strings, function ($left, $right) {
return ((($posLeft = strpos(strtolower($left['label']), 'm')) === false)
? PHP_INT_MAX
: $posLeft)
- ((($posRight = strpos(strtolower($right['label']), 'm')) === false)
? PHP_INT_MAX
: $posRight);
});
var_dump($strings);
Just compares the position of the letter within the two strings. If the letter is not within one of the strings (strpos() returns false), it assumes an "infinite" index (PHP_INT_MAX),
this is an example i found on php.net that could help you and maintain the index : http://www.php.net/manual/en/function.sort.php#99419
Sort the data by the value based on the comparison reflecting the letter (Demo):
<?php
# the data
$data = array(
0 => array(
'value' => 5,
'label' => 'Akon',
),
1 => array(
'value' => 6,
'label' => 'Angel',
),
2 => array(
'value' => 7,
'label' => 'Britny',
),
3 => array(
'value' => 9,
'label' => 'Mark Anthony',
),
4 => array(
'value' => 8,
'label' => 'Michel',
),
5 => array(
'value' => 4,
'label' => 'Shaggy',
),
6 => array(
'value' => 3,
'label' => 'Smith',
),
);
# the letter
$letter = 'M';
# the value to compare against
$value = function(array $a)
{
$key = 'label';
if (!array_key_exists($key, $a))
{
throw new InvalidArgumentException(sprintf('Key "%s" missing.', $key));
}
return $a[$key];
};
# the comparison
$compare = function($a, $b) use ($letter, $value)
{
$a = $value($a);
$b = $value($b);
if($a[0] != $b[0]) {
if($a[0] === $letter) return -1;
if($b[0] === $letter) return +1;
}
return strcmp($a, $b);
};
# the sort
$sort = function() use ($data, $compare)
{
$r = uasort($data, $compare);
if (!$r)
{
throw new RuntimeException('Sort failed.');
}
return $data;
};
print_r($sort());
Use usort to sort by a function. The function can contain any logic you want to put in, as long as the return value indicates sort order (see link for details).