PHP array sort mutli-dimensional - php

I have an array structured like so (this is the way the CSV formats it):
Array(
0 => Array(
0 => person1
1 => person2
2 => person3
//all the way to 9
),
1 => Array(
0 => id belonging to person 1
1 => id belonging to person 2
2 => id belonging to person 3
),
2 => Array(
0 => id belonging to person 1
1 => id belonging to person 2
2 => id belonging to person 3
),
//all the way to 20
)
I'm trying to sort a new array (of arrays), with each index being the value correspondent to the key in the 0 index above. i.e., person1 points to an array with all ids from the arrays 1-20 outside.
In each of the arrays after the index 0, it contains 20 ids, 0 belongs to the key 0 in the first array.
The structure I'm trying to achieve is shown below:
Array(
[person1] => Array(
id belonging to person 1
id belonging to person 1
id belonging to person 1
),
[person2] => Array(
id belonging to person 2
id belonging to person 2
id belonging to person 2
),
[person3] => Array(
id belonging to person 3
id belonging to person 3
id belonging to person 3
),
)
My attempt so far has worked, however, I had to hard code some of the indexes. What's the best solution to achieve the desired structure?

I'm a bit unsure if this is what you are looking for...
<?php
$arr = Array(
0 => Array(
0 => "person1",
1 => "person2",
2 => "person3"
//all the way to 9
),
1 => Array(
0 => "id belonging to person 1",
1 => "id belonging to person 2",
2 => "id belonging to person 3"
),
2 => Array(
0 => "id belonging to person 1",
1 => "id belonging to person 2",
2 => "id belonging to person 3"
)
);
foreach($arr[0] AS $id=>$name)
{
$ids[$id] = $name;
}
foreach(array_slice($arr,1) AS $persons)
{
foreach($persons AS $id=>$person)
{
// make sure to check if $ids[$id] exist and handle it as you like.
// if(isset($ids[$id]))
$people[$ids[$id]][] = $person;
}
}
print_r($people);
?>
result:
Array
(
[person1] => Array
(
[0] => id belonging to person 1
[1] => id belonging to person 1
)
[person2] => Array
(
[0] => id belonging to person 2
[1] => id belonging to person 2
)
[person3] => Array
(
[0] => id belonging to person 3
[1] => id belonging to person 3
)
)
EDIT: Should be noted I'm not making any checks on if the person's id exist in the $ids array, and neither if $people are ever set.

Related

How to create a three dimensional array from sql query PHP

I have 2 tables in a database, 1 of them are linked with a foreign key to the first one. Each row on table 1 is linked to multiple rows in table 2. I am trying to make a query that looks at a WHERE from table 2 and returns multiple rows from table 2 which are sorted into the rows they linked with in table 1 and then put this all into one big multi dimensional array, so it should work something like this:
$array[0][column_name][0] this would use row 1 from table 1 and give me a the first result in the column called column_name
$array[1][column_name][0] this would use row 2 from table 1 and give me a the first result in the column called column_name
$array[1][column_name][3] this would use row 2 from table 1 and give me a the 4th result in the column called column_name
etc
How can I query this and store it in a 3 dimensional array using PHP.
I have tried to word this in as clear manner as possible, if you are unsure what I am asking, please comment and I will update my question to make it clearer.
Assume that we have two tables, Company and Employee:
Company
------------------
ID Company_Name
1 Walmart
2 Amazon.com
3 Apple
Employee
---------------------------------
ID Company_Id Employee_Name
1 1 Sam Walton
2 1 Rob Walton
3 1 Jim Walton
4 1 Alice Walton
5 2 Jeff Bezos
6 2 Brian T. Olsavsky
7 3 Steve Jobs
8 3 Tim Cook
The easiest way to envision a multi-dimensional (nested) array is to mimic the looping required to get it: outer loop is the company, inner loop is the employees:
// ignoring database access, this is just pseudo code
$outer = [];
// select id, company_name from company
foreach $companyResult as $companyRow {
// select * from employee where company_id = ? {$companyRow['id']}
$inner= [];
foreach $employee_result as $employeeRow {
$inner[] = $employeeRow; // ie, ['id'=>'1','Company_Id'=>'1','Employee_Name'=>'Sam Walton']
}
$outer[] = $inner;
}
print_r($outer);
// yields ====>
Array
(
[0] => Array
(
[0] => Array
(
[id] => 1
[Company_Id] => 1
[Employee_Name] => Sam Walton
)
[1] => Array
(
[id] => 2
[Company_Id] => 1
[Employee_Name] => Rob Walton
)
[2] => Array
(
[id] => 3
[Company_Id] => 1
[Employee_Name] => Jim Walton
)
[3] => Array
(
[id] => 4
[Company_Id] => 1
[Employee_Name] => Alice Walton
)
)
[1] => Array
(
[0] => Array
(
[id] => 5
[Company_Id] => 2
[Employee_Name] => Jeff Bezos
)
[1] => Array
(
[id] => 6
[Company_Id] => 2
[Employee_Name] => Brian T. Olsavsky
)
)
[2] => Array
(
[0] => Array
(
[id] => 7
[Company_Id] => 3
[Employee_Name] => Steve Jobs
)
[1] => Array
(
[id] => 8
[Company_Id] => 3
[Employee_Name] => Tim Cook
)
)
)
It is also possible to do if you use associative arrays. Consider the flat file that this query produces:
select company.id company_id, company.name company_name,
emp.id employee_id, emp.employee_name
from company
inner join employee on company.id = employee.company_id
-----
company_id company_name employee_id employee_name
1 Walmart 1 Sam Walton
1 Walmart 2 Rob Walton
1 Walmart 3 Jim Walton
1 Walmart 4 Alice Walton
2 Amazon.com 5 Jeff Bezos
2 Amazon.com 6 Brian T. Olsavsky
3 Apple 7 Steve Jobs
3 Apple 8 Tim Cook
Just use the primary IDs as the keys for your arrays:
$employeeList = [];
foreach($result as $row) {
$cid = $row['company_name'];
$eid = $row['employee_name'];
// avoid uninitialized variable
// $employeeList[$row['company_name']] = $employeeList[$row['company_name']] ?? [];
// easier to read version of above
$employeeList[$cid] = $employeeList[$cid] ?? [];
// assign it...
$employeeList[$cid][$eid] = $row;
}
Or, if you simply want each company row to hold an array of employee names,
$employeeList[$cid][] = $row['employee_name'];
The way that I've shown you is useful if you know the company_id and want to find the associated rows:
foreach($employeeList[2] as $amazon_guys) { ... }
But it's not at all useful if you're trying to group by employee, or some other field in the employee table. You'd have to organize the order of your indexes by your desired search order.
In the end, it's almost always better to simply do another query and let the database give you the specific results you want.

getting index of outer array if there's a match in inner array

when i print_r my array gives
Array (
[0] => Array ( [userid] => 2 [popularity] => 41.7 )
[1] => Array ( [userid] => 5 [popularity] => 33.3 )
[2] => Array ( [userid] => 7 [popularity] => 25.0 )
)
is the array returned after querying users and sort by popularity desc, meaning
user with id 2 has popularity 41.7, user with id 5 has popularity 33.3 and so on,
Then i have a dynamic query that shows each user with his popularity
example: user with id 2 has popularity of 41.7
user with id 5 has popularity of 33.3 etc.
All i want is to show the position(outer array index) of each user if user id of dynamic query matches the output of array above then increment by 1 because array index always starts 0
example: user with id 2, will have position of 1 (the winner)
user with id 5, will have position of 2
user with id 7, will have position of 3 etc..
how can i do that...
This code modifies array and ads new key 'position' (= $key + 1) to each element.
function addPosition(&$item, $key) {
$item['position'] = $key + 1;
}
array_walk($data, 'addPosition');

CakePHP containable searches

I'm using Cake 2.3.8 and having a bit of trouble searching for data efficiently. I'm retrieving the data I'm looking for, but also a lot of stuff I don't need due to containables.
For example Say I have the following tables
table reservations
id | confirmation_number | guest_id
1 123 1
2 345 2
table reservation_details -a reservation can have multiple entries (multiple rooms)
id | reservation_id | date | time | room_id | rate
2 1 2014-18-04 13:00 1 9.99
4 1 2014-18-04 14:00 2 4.99
5 2 2014-19-04 13:00 2 4.99
With the following models
//Reservation model
public $actsAs = array('Containable');
public $hasMany = array('ReservationDetail');
//ReservationDetail model
public $actsAs = array('Containable');
public $belongsTo = array('Reservation');
Now perform a search for reservations where the date is greater or equal to the 19th. The date is stored in the reservation_details table.
$reservations = $this->Reservation->find('all', array(
'conditions' => array(
'Reservation.guest_id' => '1'
),
'contain' => array(
'ReservationDetail' => array(
'conditions' => array(
'ReservationDetail.date >=' => '2014-19-04'
)
)
)
));
This search would return Reservation #1, an empty array for ReservationDetail for reservation #1. The issue is I don't want any of that information. I only want data to be returned if the ReservationDetail conditions matches my search. Right now, it's only returning an empty array for ReservationDetail if the match isn't found.
The result of the above search would be something like
Array(
[0] => array //I don't want this index to be returned at all because the reservation_details weren't met
(
[Reservation] => array
(
id => 1
confirmation_number => 123
guest_id => 1
)
[ReservationDetail] => array
(
)
)
[1] => array
(
[Reservation] => array
(
id => 2
confirmation_number => 345
guest_id => 2
)
[ReservationDetail] => array
(
id => 5
reservation_id => 2
date => 2014-19-04
time => 13:00
room_id => 2
rate => 4.99
)
)
)
As you can see, the ReservationDetail for the first result found did not meet my criteria. It still returns Reservation table and an empty array for ReservationDetail.
Is there some other way I can search so that the reservation table won't be returned at all if the ReservationDetail doesn't match my criteria?
$reservations = $this->Reservation->find('all', array(
'conditions' => array(
'Reservation.guest_id' => 1,
'ReservationDetail.date >=' => '2014-19-04'
),
'joins' => array(
array(
'table' => 'reservation_details',
'alias' => 'ReservationDetail',
'type' => 'inner',
'conditions' => array(
'ReservationDetail.reservation_id = Reservation.id'
)
)
),
'contain' => array(
'ReservationDetail'
)
));

check if a value exist in array from database query

I am trying to build a website that will display the text in multiple languages.
I have a table 'text' with all the languages. If the text does not exist in the chosen language it has to display the default language.
query SELECT * FROM text WHERE TextId = 10
results in
Id TextId LanguageId Text
10 10 1 first name
13 10 2 名前
If I r_print this result I get something like this
Array ( [0] => Array ( [0] => 10 [Id] => 10 [1] => 10 [TextId] => 10 [2] => 1 [LanguageId] => 1 [3] => first name [Text] => first name )
[1] => Array ( [0] => 13 [Id] => 13 [1] => 10 [TextId] => 10 [2] => 2 [LanguageId] => 2 [3] => 名前 [Text] => 名前 ) )
How can I check that LanguageId 2 exist in this array ?
the problem is that it is possible that TextId 2 and Id 2 can also exist in this array.
Is this possible to do with in_array()?
Here is a function that can check if LanguageId equals a special value .
function isLanguageIdExists($yourArray , $LanguageId){
$exists=false;
foreach($yourArray as $array){
if(isset($array['LanguageId'])&& $array['LanguageId'] == $LanguageId){
$exists=true;break;
}
}
return $exists;
}
$exist = isLanguageIdExists($yourArray , 2);//return true or false
You can check by isset the key and match the value in php.
$dataArray = array(
0 => array(0 => 10 ,'Id' => 10, 1 => 10, 'TextId' => 10, 2 => 1, 'LanguageId' => 1),1 => array(0 => 10 ,'Id' => 10, 1 => 10, 'TextId' => 10, 2 => 1, 'LanguageId' => 1)
);
foreach($dataArray as $value) {
if(isset($value['LanguageId']) && $value['LanguageId'] == 2) {
echo 'language ID 2 is available';
}
}
Working Demo
After giving this some more thought I came up with a maybe not so elegant solution.
Instead of getting an array back I modified the SQL Query to give one row back with the default language (English) and a user selected language (Japanese).
It uses two left joins. This shows that I received (some) training in SQL but am really not at ease with multidimensional arrays.
Query
def_text = text in default language
usr_text = text in user chosen language
$table01 = "text";
$query="SELECT $table01.TextId,
text_def.Text as def_text,
text_usr.Text as usr_text
FROM $table01
LEFT JOIN $table01 as text_def ON $table01.TextId = text_def.TextId AND text_def.LanguageId = $_SESSION[default_language]
LEFT JOIN $table01 as text_usr ON $table01.TextId = text_usr.TextId AND text_usr.LanguageId = $_SESSION[language]
WHERE $table01.TextId=$mess;";
after getting back the results it is easy to check with isset() or empty() to see if the text is available in the user selected language

Filter two multidimensional arrays based on key matches, but each array has different structure - Output to new merged array

I am trying to extract only array items that match on specific fields and then I need to merge the two into one array only containing the data I need.
I have two arrays, and their structure is like below. Only product_count s where CATEGORY_ID of Array #1 match the Key of Array #2 should be the output.
Array #1: - Many of Array #1 CATEGORY_IDs will not exist in Array #2 key field.
0 => Array (4)
0 => 3
CATEGORY_ID => 10
1 => 1
product_count => 8
1 => Array (4)
0 => 4
CATEGORY_ID => 111
1 => 6
product_count => 109
...
Array #2:
10 => Category Name 1
110 => Category Name 2
8 => Category Name 3
109 => Category Name 4
111 => Category Name 5
3 => Category Name 6
132 => Category Name 7
...
Final Output should look something like: and I might be going about this all wrong, so I am open to any suggestions..
10 => [0] => Category Name 1
[1] => 8 // product_count
111 => [0] => Category Name 5
[1] => 109 // product_count
...
I am running a foreach() to extract product counts per category. As you can see my two arrays reflect this by the data.
You'd have to do a foreach loop, I believe:
$new_array = array();
foreach($array1 as $part) {
$new_array[$part["CATEGORY_ID"]] = array( $array2[$part["CATEGORY_ID"]], $part["product_count"] );
}
I think I got the gist of what you want. I don't think there is an actual PHP function to do what you want, either.

Categories