Is it possible to sort (with php) an array like this by last name:
$array = array(
array("name" => "Mary Johnson","age" => 43),
array("name" => "Amanda Miller","age" => 23),
array("name" => "James Brown","age" => 47),
array("name" => "Patricia Williams","age" => 31),
array("name" => "Michael Davis","age" => 15),
array("name" => "Sarah Miller","age" => 35),
array("name" => "Patrick Miller","age" => 44)
);
<?php
// A function to sort by last name.
function lastNameSort($a, $b) {
$aLast = end(explode(' ', $a));
$bLast = end(explode(' ', $b));
return strcasecmp($aLast, $bLast);
}
// The array of data.
$array = array(
array("name" => "Mary Johnson","age" => 43),
array("name" => "Amanda Miller","age" => 23),
array("name" => "James Brown","age" => 47),
array("name" => "Patricia Williams","age" => 31),
array("name" => "Michael Davis","age" => 15),
array("name" => "Sarah Miller","age" => 35),
array("name" => "Patrick Miller","age" => 44)
);
// Perform the sort:
uasort($array, 'lastNameSort');
// Print the result:
print_r($array);
Its just an addressing issue. Amend you function as below, remember the $a and $b are arrays and not scalar variables.
$array = array(
array("name" => "Mary Johnson","age" => 43),
array("name" => "Amanda Miller","age" => 23),
array("name" => "James Brown","age" => 47),
array("name" => "Patricia Williams","age" => 31),
array("name" => "Michael Davis","age" => 15),
array("name" => "Sarah Miller","age" => 35),
array("name" => "Patrick Miller","age" => 44)
);
function sortByName($a, $b) {
$aLast = explode(' ', $a['name'])[1];
$bLast = explode(' ', $b['name'])[1];
return strcasecmp($aLast, $bLast);
}
#print_r($array);
usort($array, 'sortByName');
print_r($array);
RESULT
Array
(
[0] => Array ( [name] => James Brown [age] => 47 )
[1] => Array ( [name] => Michael Davis [age] => 15 )
[2] => Array ( [name] => Mary Johnson [age] => 43 )
[3] => Array ( [name] => Amanda Miller [age] => 23 )
[4] => Array ( [name] => Sarah Miller [age] => 35 )
[5] => Array ( [name] => Patrick Miller [age] => 44 )
[6] => Array ( [name] => Patricia Williams [age] => 31 )
)
And to get the Millers in the correct order by firstname as well as lastname, you code amend the sort function a little as below
function sortByName($a, $b) {
$t = explode(' ', $a['name']);
$aLast = $t[1] . $t[0];
$t = explode(' ', $b['name'])[1];
$bLast = $t[1] . $t[0];
return strcasecmp($aLast, $bLast);
}
Related
This question already has answers here:
Merge row data from multiple arrays
(6 answers)
Closed 4 months ago.
I'm currently stuck on how to merge multi query result into single result like;
multiple result:
$a1 = array(
["name" => "coca-cola"],
["name" => "sprite"],
["name" => "pepsi"]
);
$a2 = array(
["color" => "red"],
["color" => "green"],
["color" => "blue"]
);
$a3 = array(
["price" => 2],
["price" => 1],
["price" => 4]
);
expected output:
$res = array(
["name" => "coca-cola","color" => "red", "price" => 2],
["name" => "sprite","color" => "green", "price" => 1],
["name" => "pepsi","color" => "blue", "price" => 4]
);
Try this solution.
$a1 = array(
["name" => "coca-cola"],
["name" => "sprite"],
["name" => "pepsi"]
);
$a2 = array(
["color" => "red"],
["color" => "green"],
["color" => "blue"]
);
$a3 = array(
["price" => 2],
["price" => 1],
["price" => 4]
);
$res = array();
for($i=0; $i<count($a1); $i++){
$res[] = array_merge($a1[$i],$a2[$i],$a3[$i]);
}
Here we are assuming that all $a1, $a3, $a3 arrays have the same dimension.
One more solution:
$result = array_map(
function($name, $color, $price) {
return array_merge($name, $color, $price);
},
$a1, $a2, $a3
);
print_r($result);
share PHP code
Array
(
[0] => Array
(
[name] => coca-cola
[color] => red
[price] => 2
)
[1] => Array
(
[name] => sprite
[color] => green
[price] => 1
)
[2] => Array
(
[name] => pepsi
[color] => blue
[price] => 4
)
)
I have a 2D array that its first dimension is an index array and the second one is an associative array.
In the array, there are some duplicates fields that I want to merge them, and for the other unduplicated fields, I want to make a third dimension array and push them there.
This is my code and array:
The entire code works correctly just the "datacontractor" field that is my third dimension does not work well.
<?php
$array=Array
(
"0" => Array
(
"sid" => 10,
"contractorid" => 1,
"fname" => "hi",
"lname" => "fam",
"sname" => "saba",
"materialname" => "beton",
"netweight" => 100,
),
"1" => Array
(
"sid" => 16,
"contractorid" => 2,
"fname" => "a",
"lname" => "a",
"sname" => "khoram",
"materialname" => "kk",
"netweight" => 200,
),
"2" => Array
(
"sid" => 16,
"contractorid" => 7,
"fname" => "a",
"lname" => "a",
"sname" => "khoram",
"materialname" => "kk",
"netweight" => 777,
),
"3" => Array
(
"sid" => 10,
"contractorid" => 5,
"fname" => "hi",
"lname" => "fam",
"sname" => "saba",
"materialname" => "beton",
"netweight" => 200,
),
"4" => Array
(
"sid" => 10,
"contractorid" => 8,
"fname" => "hi",
"lname" => "fam",
"sname" => "saba",
"materialname" => "beton",
"netweight" => 600,
),
"5" => Array
(
"sid" => 15,
"contractorid" => 9,
"fname" => "hi",
"lname" => "fam",
"sname" => "saba",
"materialname" => "beton",
"netweight" => 400,
),
);
$finalarray[]= array();
$sidlist= array();
$arraycount=count($array);
for($i=0;$i<$arraycount ;$i++) {
array_push($sidlist,$array[$i]["sid"]);
}
$sidlist = array_unique($sidlist);
$sidlistcount=count($sidlist);
$sidlist1=array();
foreach ($sidlist as $m){
array_push($sidlist1,$m);
}
for ($i = 0;$i<$sidlistcount ; $i++){
$id=$sidlist1[$i];
$datacontractor[$id]= array();
for ($j = 0;$j<$arraycount ; $j++){
if ($id==$array[$j]["sid"]){
$contractorid = $array[$j]["contractorid"];
$netweight = $array[$j]["netweight"];
$finalarray[$i]=array(
"sid" => $id,
"fname" => $array[$j]["fname"],
"lname" => $array[$j]["lname"],
"sname" => $array[$j]["sname"],
"materialname" => $array[$j]["materialname"],
"datacontractor" => $datacontractor[$id],
);
$datacontractor[$id]["$contractorid"]=$netweight;
echo $id,"<br>";
}
}
}
echo '<pre>';
print_r($finalarray);
echo '<pre>';
This is my output of this code:
but it has wrong answer in "datacontractor" field.
Array ([0] => Array
(
[sid] => 10
[fname] => hi
[lname] => fam
[sname] => saba
[materialname] => beton
[datacontractor] => Array
(
[1] => 100
[5] => 200
)
)[1] => Array
(
[sid] => 16
[fname] => a
[lname] => a
[sname] => khoram
[materialname] => kk
[datacontractor] => Array
(
[2] => 200
)
)[2] => Array
(
[sid] => 15
[fname] => hi
[lname] => fam
[sname] => saba
[materialname] => beton
[datacontractor] => Array
(
)
))
And Finally My desired output is:
Please check and tell me what my fault is.
Array ([0] => Array
(
[sid] => 10
[fname] => hi
[lname] => fam
[sname] => saba
[materialname] => beton
[datacontractor] => Array
(
[1] => 100
[5] => 200
[8] => 600
)
)[1] => Array
(
[sid] => 16
[fname] => a
[lname] => a
[sname] => khoram
[materialname] => kk
[datacontractor] => Array
(
[2] => 200
[7] => 777
)
)[2] => Array
(
[sid] => 15
[fname] => hi
[lname] => fam
[sname] => saba
[materialname] => beton
[datacontractor] => Array
(
[9] => 400
)
))
You set the "datacontractor" => $datacontractor[$id] to finalarray before finish insert all the data to the $datacontractor[$id] -> do that in separate loop.
You code is much more complicated then you actually need.
Consider the following short version:
$array = []; // this is just some of the fields - you can add all of then here
$array[] = array("id"=> 10, "contractorid" => 1,"netweight" => 100);
$array[] = array("id"=> 16, "contractorid" => 2,"netweight" => 200);
$array[] = array("id"=> 16, "contractorid" => 7,"netweight" => 777);
$array[] = array("id"=> 10, "contractorid" => 5,"netweight" => 200);
$array[] = array("id"=> 10, "contractorid" => 8,"netweight" => 600);
$array[] = array("id"=> 15, "contractorid" => 9,"netweight" => 400);
$ans = [];
foreach($array as $e) {
if (!isset($ans[$e['id']])) { // if never set do first time
$ans[$e['id']] = array("sid" => $e['id'], "datacontractor" => array($e["contractorid"] => $e["netweight"])); // here you can add all your other fields as fname, lname...
} else {
$ans[$e['id']]["datacontractor"][$e["contractorid"]] = $e["netweight"]; // just add the new field as already set
}
}
Now, $ans will output your desire
Edit:
For having multi contractorid value change to this:
foreach($array as $e) {
if (!isset($ans[$e['id']])) { // if never set do first time
$ans[$e['id']] = array("sid" => $e['id'], "datacontractor" => array($e["contractorid"] => [$e["netweight"]])); // notice "contractorid" has array inside (extra "[]" around $e["netweight"])
} else {
$ans[$e['id']]["datacontractor"][$e["contractorid"]][] = $e["netweight"]; // append to the contractorid array
}
}
For re-index $ans do this at the end: $ans = array_values($ans);
You can use array_reduce
$data = array_reduce($array, function ($old, $new) {
if (isset($old[$new['sid']])) {
$new['datacontractor'] = array_merge($old[$new['sid']]['datacontractor'], [$new['netweight']]);
$old[$new['sid']] = $new;
} else {
$new['datacontractor'] = [$new['netweight']];
}
unset($new['netweight']);
$old[$new['sid']] = $new;
return $old;
}, []);
$data = array_values($data);
print '<pre>';
print_r($data);
print '</pre>';
I have a multidimensional array, in which I have a few set of values. What I want to do here is to merge the key values "marks" and "course" if the values of the key "name" match. So far, I've done something like below to remove the duplicates:
$multi = array(
array("name" => "Michael", "marks" => "25, 27, 34", "course" => "ABC"),
array("name" => "Kumar", "marks" => "59, 71, 38", "course" => "DEF"),
array("name" => "Peter", "marks" => "94, 43, 61", "course" => "JKL"),
array("name" => "Kumar", "marks" => "83, 57, 73", "course" => "GHI"),
);
$multiTemp = $multiNew = array();
foreach($multi as $key=>$val){
if(array_key_exists($val['name'], $multiTemp) ) {
continue;
}
$multiTemp[$val['name']] = 1;
$multiNew[] = $val;
}
echo "<pre>";
print_r($multiNew);
echo "</pre>";
It just removes the duplicate values. Is therey any way to merge the other two values based on the condition I mentioned above the code? Just like the second and fourth array in the array $multi carry same values for name, so I want marks and course to be mereged into one. Thanks in advance for your help.
Current Output:
Array
(
[0] => Array
(
[name] => Michael
[marks] => 25, 27, 34
[course] => ABC
)
[1] => Array
(
[name] => Kumar
[marks] => 59, 71, 38
[course] => DEF
)
[2] => Array
(
[name] => Peter
[marks] => 94, 43, 61
[course] => JKL
)
)
Expected Output:
Array
(
[0] => Array
(
[name] => Michael
[marks] => 25, 27, 34
[course] => ABC
)
[1] => Array
(
[name] => Kumar
[marks] => 59, 71, 38, 83, 57, 73
[course] => DEF, GHI
)
[2] => Array
(
[name] => Peter
[marks] => 94, 43, 61
[course] => JKL
)
)
array_reduce() + arrray_values() solution:
$multi = [
["name" => "Michael", "marks" => "25, 27, 34", "course" => "ABC"],
["name" => "Kumar", "marks" => "59, 71, 38", "course" => "DEF"],
["name" => "Peter", "marks" => "94, 43, 61", "course" => "JKL"],
["name" => "Kumar", "marks" => "83, 57, 73", "course" => "GHI"]
];
$result = array_values(array_reduce($multi, function($r, $a){
$name = $a['name'];
if (isset($r[$name])){
$r[$name]['marks'] .= ', ' . $a['marks'];
$r[$name]['course'] .= ', ' . $a['course'];
} else {
$r[$name] = $a;
}
return $r;
}, []));
print_r($result);
The output:
Array
(
[0] => Array
(
[name] => Michael
[marks] => 25, 27, 34
[course] => ABC
)
[1] => Array
(
[name] => Kumar
[marks] => 59, 71, 38, 83, 57, 73
[course] => DEF, GHI
)
[2] => Array
(
[name] => Peter
[marks] => 94, 43, 61
[course] => JKL
)
)
http://php.net/manual/en/function.array-reduce.php
Lets say, I have the following array:
$array = array(
array(
"id" => 1,
"name" => "Europe",
"path" => "/"
),
array(
"id" => 2,
"name" => "Germany",
"path" => "/1/"
),
array(
"id" => 3,
"name" => "France",
"path" => "/1/"
),
array(
"id" => 4,
"name" => "Berlin",
"path" => "/1/2/"
),
array(
"id" => 5,
"name" => "Munich",
"path" => "/1/2/"
)
);
As you can see, its a multidimensional array with 3 properites in earch 2nd level array: id, name and path. The path is a path structure based on the parent-id of its parent. For example, Germany (id=2) has belongs to Europe, so the path is "/1/" (ID 1 = Europe) and Berlin in Germany has the path "/1/2/" which means "/Europe/Germany/"
Now, I am trying to create a tree-array out of this, which should somehow look like:
$result = array(
1 => array(
"id" => 1,
"name" => "Europe",
"path" => "/",
"childs" => array(
2 => array(
"id" => 2,
"name" => "Germany",
"path" => "/1/",
"childs" => array(
4 => array(
"id" => 4,
"name" => "Berlin",
"path" => "/1/2/"
),
5 => array(
"id" => 5,
"name" => "Munich",
"path" => "/1/2/"
)
)
),
3 => array(
"id" => 3,
"name" => "France",
"path" => "/1/"
)
)
)
);
I have already tried to create a function with internal references, but this didn't works for me:
public static function pathToTree($items) {
$array = array();
$result = array();
foreach($items AS $res) {
$ids = explode("/", ltrim($res["path"] . $res["id"], "/"));
$count = count($ids);
$tmp = &$result;
foreach( $ids AS $id) {
if($count == 1) {
$tmp = $res;
$tmp["childs"] = array();
$tmp = &$tmp["childs"];
}
else {
$tmp[$id] = array(
"childs" => array()
);
$tmp = &$tmp[$id]["childs"];
}
$count--;
}
}
return $array;
}
Ok, I think I just found a solution:
function pathToTree($array){
$tree = array();
foreach($array AS $item) {
$pathIds = explode("/", ltrim($item["path"], "/") . $item["id"]);
$current = &$tree;
foreach($pathIds AS $id) {
if(!isset($current["childs"][$id])) $current["childs"][$id] = array();
$current = &$current["childs"][$id];
if($id == $item["id"]) {
$current = $item;
}
}
}
return $tree["childs"];
}
This is a dynamice solution for 1-n depth. Look at my example at http://ideone.com/gn0XLp . Here I tested it with some level:
Continent
Country
City
City-District
City-Subdistrict
City Sub-Sub-District
I've created a recursive function:
// The array
$array = array(
array(
"id" => 1,
"name" => "Europe",
"path" => "/"
),
array(
"id" => 2,
"name" => "Germany",
"path" => "/1/"
),
array(
"id" => 3,
"name" => "France",
"path" => "/1/"
),
array(
"id" => 4,
"name" => "Berlin",
"path" => "/1/2/"
),
array(
"id" => 5,
"name" => "Munich",
"path" => "/1/2/"
),
array(
"id" => 6,
"name" => "Asia",
"path" => "/"
),
array(
"id" => 7,
"name" => "India",
"path" => "/6/"
),
array(
"id" => 7,
"name" => "Mumbai",
"path" => "/6/7"
),
array(
"id" => 8,
"name" => "Delhi",
"path" => "/6/7"
),
);
// The recursive function
function createTree($input, &$result = array(), $key = null) {
if ($key == "id") {
$result["temp"]["id"] = $input;
}
if ($key == "name") {
$result["temp"]["name"] = $input;
}
if ($key == "path") {
$result["temp"]["path"] = $input;
$levels = is_string($input) ? array_values(array_filter(explode('/', $input))) : null;
if ($input == "/") {
$result[$result["temp"]["id"]] = $result["temp"];
}
if (count($levels) == 1) {
$result[$levels[0]]["childs"][$result["temp"]["id"]] = $result["temp"];
}
if (count($levels) == 2) {
$result[$levels[0]]["childs"][$levels[1]]["childs"][$result["temp"]["id"]] = $result["temp"];
}
unset($result["temp"]);
}
if (is_array($input)) {
foreach($input as $key => $value) {
createTree($value, $result, $key);
}
}
return $result;
}
// The result
array (
1 =>
array (
'id' => 1,
'name' => 'Europe',
'path' => '/',
'childs' =>
array (
2 =>
array (
'id' => 2,
'name' => 'Germany',
'path' => '/1/',
'childs' =>
array (
4 =>
array (
'id' => 4,
'name' => 'Berlin',
'path' => '/1/2/',
),
5 =>
array (
'id' => 5,
'name' => 'Munich',
'path' => '/1/2/',
),
),
),
3 =>
array (
'id' => 3,
'name' => 'France',
'path' => '/1/',
),
),
),
6 =>
array (
'id' => 6,
'name' => 'Asia',
'path' => '/',
'childs' =>
array (
7 =>
array (
'id' => 7,
'name' => 'India',
'path' => '/6/',
'childs' =>
array (
7 =>
array (
'id' => 7,
'name' => 'Mumbai',
'path' => '/6/7',
),
8 =>
array (
'id' => 8,
'name' => 'Delhi',
'path' => '/6/7',
),
),
),
),
),
)
As I said in the comment, you need at least three loops to achieve your goals. Here's the function:
function pathToTree($array){
$tree = Array();
for($i=0; $i < count($array); $i++){
if(substr_count($array[$i]["path"], '/') == 1)
$tree[$array[$i]["id"]] = $array[$i];
}
for($i=0; $i < count($array); $i++){
if(substr_count($array[$i]["path"], '/') == 2){
$num = (int)str_replace("/","",$array[$i]["path"]);
$tree[$num]["childs"][$array[$i]["id"]] = $array[$i];
}
}
for($i=0; $i < count($array); $i++){
if(substr_count($array[$i]["path"], '/') == 3){
$num = explode("/", $array[$i]["path"]);
$tree[$num[1]]["childs"][$num[2]]["childs"][$array[$i]["id"]] = $array[$i];
}
}
return $tree;
}
Example:
Consider this array:
$array = array(
array(
"id" => 1,
"name" => "Europe",
"path" => "/"
),
array(
"id" => 2,
"name" => "Germany",
"path" => "/1/"
),
array(
"id" => 3,
"name" => "France",
"path" => "/1/"
),
array(
"id" => 4,
"name" => "Berlin",
"path" => "/1/2/"
),
array(
"id" => 5,
"name" => "Munich",
"path" => "/1/2/"
),
array(
"id" => 6,
"name" => "Asia",
"path" => "/"
),
array(
"id" => 7,
"name" => "China",
"path" => "/6/"
),
array(
"id" => 8,
"name" => "Bangladesh",
"path" => "/6/"
),
array(
"id" => 9,
"name" => "Beijing",
"path" => "/6/7/"
),
array(
"id" => 10,
"name" => "Dhaka",
"path" => "/6/8/"
)
);
if I ran this code:
print_r(pathToTree($array));
the output will be:
Array
(
[1] => Array
(
[id] => 1
[name] => Europe
[path] => /
[childs] => Array
(
[2] => Array
(
[id] => 2
[name] => Germany
[path] => /1/
[childs] => Array
(
[4] => Array
(
[id] => 4
[name] => Berlin
[path] => /1/2/
)
[5] => Array
(
[id] => 5
[name] => Munich
[path] => /1/2/
)
)
)
[3] => Array
(
[id] => 3
[name] => France
[path] => /1/
)
)
)
[6] => Array
(
[id] => 6
[name] => Asia
[path] => /
[childs] => Array
(
[7] => Array
(
[id] => 7
[name] => China
[path] => /6/
[childs] => Array
(
[9] => Array
(
[id] => 9
[name] => Beijing
[path] => /6/7/
)
)
)
[8] => Array
(
[id] => 8
[name] => Bangladesh
[path] => /6/
[childs] => Array
(
[10] => Array
(
[id] => 10
[name] => Dhaka
[path] => /6/8/
)
)
)
)
)
)
Here's the phpfiddle link in case you might try it yourself.
I have three arrays & i like to convert it in one multidimensional array.
$array1=array('Kathy', 'Adam', 'Jenny');
$array2=array('student','teacher','driver');
$array3=array(2, 5, 8);
$mix=array();
$mix['name']=array_values( $array1);
$mix['profession']=array_values( $array2);
$mix['SL']=array_values( $array3);
& from those arrays i can get below output:
Array
(
[name] => Array
(
[0] => Kathy
[1] => Adam
[2] => Jenny
)
[profession] => Array
(
[0] => student
[1] => teacher
[2] => driver
)
[SL] => Array
(
[0] => 2
[1] => 5
[2] => 8
)
)
Now i would like to get below output from above... anybody please help me how to do this ?
[0]=>Array
(
[name] => Kathy
[profession] =>student
[SL] => 2
)
[1]=>Array
(
[name] => Adam
[profession] =>teacher
[SL] => 5
)
[2]=>Array
(
[name] => Jenny
[profession] =>driver
[SL] => 8
)
You can use array_map function to do that:
<?php
$array1 = array('Kathy', 'Adam', 'Jenny');
$array2 = array('student','teacher','driver');
$array3 = array(2, 5, 8);
$mix = array_map(
function ($name, $profession, $sl) {
return array('name' => $name, 'profession' => $profession, 'SL' => $sl);
},
$array1,
$array2,
$array3
);
$array1=array('Kathy', 'Adam', 'Jenny');
$array2=array('student','teacher','driver');
$array3=array(2, 5, 8);
$mix = array();
foreach ($array1 as $index => $val)
{
$mix[] = array(
'name' => $val,
'profession' => $array2[$index],
'SL' => $array3[$index]);
}
Use this:
$array1=array('Kathy', 'Adam', 'Jenny');
$array2=array('student','teacher','driver');
$array3=array(2, 5, 8);
$mix=array();
for($i=0;$i<count($array1);$i++){
$mix[$i]=array('name'=>$array1[$i],'profession'=>$array2[$i],'SL'=>$array3[$i]);
}
print_r($mix);
Use this if all of array has same size.
No problems, you can use this code:
$array1=array('Kathy', 'Adam', 'Jenny');
$array2=array('student','teacher','driver');
$array3=array(2, 5, 8);
$mix=array();
if (count($array1)==count($array2) && count($array2)==count($array3)){
$count = count($array1);
for ($i=0;$i<$count;$i++){
$mix[] = array(
'name' => isset($array1[$i]) ? $array1[$i] : '',
'profession' => isset($array2[$i]) ? $array2[$i] : '',
'SL' => isset($array3[$i]) ? $array3[$i] : '',
);
}
}