First of all, I'm sorry if this is too easy for many of you... I'm learning as much as I can.
I want to create an array with customers, like:
$customers=["customer A", "customer B", "customer C"];
Then, I want to create an array with some characteristics for every customer in that array. The characteristics are 'City', 'Points' and 'Results'. Each customer has a name (string), not a number.
I would need to change (or update) a characteristic ('points') of all customers of the array when needed with PHP. Something like:
for each $customer in $customers {
$points[$customer]=$points[$customer]+2;
}
I would like to also update the info of only one customer, something like:
$points['Customer C']=$points['Customer B']+3;
Finally, I need to access the characteristics of a give Customer, like:
$i=$points['Customer A']+$result['Customer A'];
I know this is not correct, but how should I proceed in PHP?
How could I eliminate a Customer from the array $Customers (with all its characteristics)? And how could I add a new Customer to $Customers?
Thank you very much for your help. I really appreciate it.
As your question states, assoc array:
$customers = [
'customerA' => [
'points' => 100,
'city' => 'New York',
'results' => 40,
],
'customerB' => [
'points' => 75,
'city' => 'Amsterdam',
'results' => 10,
],
'customerC' => [
'points' => 25,
'city' => 'London',
'results' => 5,
],
];
// Remove customer C
unset($customers['customerC']);
// add customer D
$customers['customerD'] = [
'points' => 50,
'city' => 'Berlin',
'results' => 5,
];
// Update points of customer
$customers['customerA']['points'] += 2; // Adds 2 points
// Update points of customer by another customers points
$customers['customerB']['points'] = $customers['customerA']['points'] + 3;
// Add 2 points to each customer
foreach ($customers as $name => $properties) {
$properties['points'] += 2;
$customers[$name] = $properties;
}
The key within the customers array is the name of your customer and all the properties are within the value of that key.
You were close with your foreach:
foreach ($customers as $customer) {
$points[$customer] = $points[$customer] + 2;
}
You can update a single value like this:
$points['customer A'] = $points['customer A'] + 2;
And you can unset/remove a value like this:
unset($points['customer A']);
$customers = array();
//Adding customers
$customers["Customer 1"]["City"] = "Houston";
$customers["Customer 1"]["points"] = 3;
$customers["Customer 1"]["Results"] = "";
$customers["Customer 2"]["City"] = "Paris";
$customers["Customer 2"]["points"] = 8;
$customers["Customer 2"]["Results"] = "";
//updating characteristics
foreach ($customers as $name=>$customer)
{
$customers[$name]["City"] = "Dallas";
$customers[$name]["points"] = $customers[$name]["points"] + 2;
$customers[$name]["Results"] = "";
}
//Removing customer
unset($customers["Customer 1"]);
You can use multidimensional arrays to hold the data. This will be like how data would be returned from a database request so is a good approach to use.
// Customers array
$customers = [
[
'name' => 'Customer A',
'city' => 'Townville',
'points' => '3',
'results' => '2',
],
[
'name' => 'Customer B',
'city' => 'Blagstonberry',
'points' => '1',
'results' => '4',
],
[
'name' => 'Customer C',
'city' => 'Thorpington',
'points' => '6',
'results' => '3',
],
];
To access or edit specific customer details you will need to get the key for that customer. For example, get the key for Customer A,
$key = array_search('Customer A', array_column($customers, 'name'));
Now to access that customer's city for example, you can use the code,
$customer_a_city = $customers[$key]['city'];
To remove Customer B,
// get the key
$key = array_search('Customer B', array_column($customers, 'name'));
// remove customer
unset($customers[$key]);
Add 2 points to all customers,
foreach ($customers as &$customer) {
$customer['points'] += 2;
}
unset($customer);
Here we are passing by reference using the &. This means we can update the value directly in the foreach loop. It is good practice to unset the variable, in this case $customer so that you don't make any unwanted changes later on.
Characteristics of a particular customer - Customer C,
// get the key
$key = array_search('Customer C', array_column($customers, 'name'));
$i = $customers[$key]['points'] + $customers[$key]['results'];
Add a customer,
$customers[] = [
'name' => 'Customer D',
'city' => 'Dongleville',
'points' => '7',
'results' => '1',
];
Notes
If you search for a key for a customer by name that doesn't exist $key will be false. For example,
// get the key
$key = array_search('MADE UP NAME', array_column($customers, 'name'));
if ($key === false) {
// customer name did not exist
} else {
// do your thing
}
Also if more than one customer has the same name, the first customer key will be returned.
Reference
Passing by reference
Array search
Array column
Related
I have an array with orders. Example:
$orders = [
'0' => [
'ordernumber' => 1,
'customer' => [
'phone' => '0123456789',
'mobile' => '0612345678'
],
],
'1' => [
'ordernumber' => 2,
'customer' => [
'phone' => '0123456789',
'mobile' => '0612345678'
],
],
'2' => [
'ordernumber' => 3,
'customer' => [
'phone' => '0987654321',
'mobile' => '0687654321'
],
],
'3' => [
'ordernumber' => 3,
'customer' => [
'phone' => '0123456789',
'mobile' => '0612345678'
],
]
];
I want to sort these orders. As you can see there can be orders where the same customer (customer with same phone number, this can be either same phone number or same mobile number) has multiple orders. I want to put all the orders that have the same phone number (doesn't matter if the phone number matches or the mobile number) in an array $duplicateOrders and all the "single" orders (orders that dont match a phone number) in an array $singleOrders. At the end the orders array must be empty. But no order can be lost or be in both arrays.
I have tried to loop through the orders with a foreach loop where I put every order in the $singleOrders array and unset it from the $orders array. I than try to match that order with another foreach loop to all the remaining orders in $orders. If I get a match i put that order (this is done once) in the $duplicateOrders array and every match of it also (I unset every match also from the $orders array). If the orders array is empty I stop, otherwise the first foreach loops kicks in and takes the next order and the proces repeats. This is my code:
protected function splitDuplicateOrders()
{
$singleOrderKey = 0;
if ($this->orders) {
foreach ($this->orders as $key => $order) {
if (count($this->orders) == 0) {
break;
}
array_push($this->singleOrders, $order);
unset($this->orders[$key]);
$orderPushed = false;
foreach ($this->orders as $otherKey => $value) {
if ($order->customer->phone == $value->customer->phone || $order->customer->mobile == $value->customer->mobile) {
if (!$orderPushed) {
array_push($this->duplicateOrders, $order);
}
array_push($this->duplicateOrders, $value);
unset($this->orders[$otherKey]);
unset($this->singleOrders[$singleOrderKey]);
$orderPushed = true;
}
}
$singleOrderKey++;
}
}
}
I expected to have an $duplicateOrders array with all the duplicates and a $singleOrders array with all the singles. I tested this with an $orders array of a total of 4 orders where 2 of them were duplicates and 2 were singles. The function sorted it nicely (but only if the orders aren't right after each other, if they are it still sorts the duplicates right but leaves one also in the $singleOrders and than I have 5 orders). Than I tested it where there were 3 duplicates and 1 single order. The $duplicateOrders array was correct but in the $singleOrders the single order was placed but also one duplicate order from the $orders array. It somehow removed the 2 duplicates correct but left one duplicate in the $singleOrders array.
Can someone help me to debug this or provide a different approach? I have been trying to solve this for 2 days but no success.
You could make use of Laravel Collections, in this case I'm gonna use the partition() method. From the documentation:
partition()
The partition method may be combined with the list PHP function to
separate elements that pass a given truth test from those that do not:
$collection = collect([1, 2, 3, 4, 5, 6]);
list($underThree, $equalOrAboveThree) = $collection->partition(function ($i) {
return $i < 3;
});
$underThree->all();
// [1, 2]
$equalOrAboveThree->all();
// [3, 4, 5, 6]
So in your case:
$orders = /** query or API to get orders as array */;
list($repeated, $single) = collect($orders)
->partition(function ($order) use ($orders) {
return $orders->where('customer.phone', $order['customer']['phone'])->count() > 1
OR $orders->where('customer.mobile', $order['customer']['mobile'])->count() > 1;
});
// now you can use them:
$repeated->all();
$single->all();
Notice that this two newly created objects ($repeated and $single) are in fact also instances of the Collection class (as you can see where I used the all() method on each), so you can keep constraining/sorting/customizing them with the help of the Collection's methods.
How Can I Create a main array that includes multiple child array And be in the form of Jason and I want to add the child Array to main array in the Loop
MainArray=[
array1=[{fname:asdada,lastname:sdsadasda}];
array2=[{fname:asdada,lastname:sdsadasda}];
array3=[{fname:asdada,lastname:sdsadasda}];
];
echo MainArray[1]->fname;
Please see the following pseudo code below:
pseudo code
You should really look into a basic php tutorial.
This is how you do it.
$mainArray = [
'array1' => ['fname' => 'asdada', 'lastname' => 'sdsadasda'],
'array2' => ['fname' => 'asdada', 'lastname' => 'sdsadasda'],
'array3' => ['fname' => 'asdada', 'lastname' => 'sdsadasda']
];
echo $mainArray['array1']['fname'];
Or use the long notation if you have an older version of php or want backwards compatibility.
$mainArray = array(
'array1' => array('fname' => 'foo', 'lastname' => 'bar'),
'array2' => array('fname' => 'lorem', 'lastname' => 'ipsum'),
'array3' => array('fname' => 'test', 'lastname' => 'example')
);
echo $mainArray['array1']['fname'];
Explanation:
The php variable sigil is $. This means that in order to access a variable or assign something to a variable, you use $mainArray. See more on variables in the documentation.
The php array can be used in two different notations. Either array(...) or, from php 5.4 upwards, [...]. Other than the opening and closing parts, they are identical. You don't use : or = to assign individual values inside an array declaration. For this you use the => operator. Each element in an array is separated by a comma (,).
E.g.
$mainArray = array(
'A' => 1,
'B' => 2
];
Arrays in Php can be either associative or numerical. What you probably want is that your outer array is numerical, meaning you can access it using $mainArray[1], and your inner array is associative. For numerical arrays, you don't specify a key yourself, so there is no need for the =>.
$mainArray = array(
array(),
array(),
array()
);
And with associative sub arrays this becomes:
$mainArray = array(
array('firstname' => 'foo', 'lastname' => 'bar'),
array('firstname' => 'test', 'lastname' => 'example'),
array('firstname' => 'lorem', 'lastname' => 'ipsum')
);
In order to access the firstname key of the first child array in this multilevel array structure, you do:
$mainArray[0]['firstname']
E.g. (if you want to echo it to the standard output)
echo $mainArray[0]['firstname'];
Please note that numerical arrays in php start counting on 0, as in most other programming languages. And please note that the key in the associative array is a string, and as such must be surrounded with either ' or ".
I can recommend you search for a php beginner's tutorial and try to write and execute the examples yourself, to get a better grasp of php. If you need somewhere to run your php examples, I can recommend you try an online php environment such as PHPFiddle.
Update on adding values:
You can add more key=>value pairs to an associative array or add more values to a numerical array afterwards in much the same way as you would access or assign to it.
First, let's add a value to a numerical array. You do this by adding [] to the end of your variable when assigning. This means that what you assign will be added as a new numerical value to the end of your array.
$numericalArray = array(
7,
8,
6,
12,
'B'
);
$numericalArray[] = 'C';
// Results in the array: array(7, 8, 6, 12, 'B', 'C')
And in order to add a new key => value pair to an associative array, you just add it using the new key, e.g.
$assoc = array(
'firstname' => 'Testy',
'lastname' => 'McTestface'
);
$assoc['middlename'] => 'Tester';
So to add a new fname-lastname pair to the mainArray, you would do:
$mainArray = array(
array('fname' => 'foo', 'lastname' => 'bar'),
array('fname' => 'test', 'lastname' => 'example'),
array('fname' => 'lorem', 'lastname' => 'ipsum')
);
$mainArray[] = array('fname' => 'new name', 'lastname' => 'new last name');
If you want to do this in a loop, you will use the for, foreach, while or do while structures.
E.g.
$mainArray = array(
array('fname' => 'foo', 'lastname' => 'bar'),
array('fname' => 'test', 'lastname' => 'example'),
array('fname' => 'lorem', 'lastname' => 'ipsum')
);
for ($i = 0; $i < 3; ++$i) {
$mainArray[] = array('fname' => 'new name ' . $i, 'lastname' => 'new last name ' . $i);
}
echo json_encode($mainArray, JSON_PRETTY_PRINT|JSON_UNESPACED_UNICODE|JSON_UNESCAPED_SLASHES), PHP_EOL;
// [
// {'fname': 'foo', 'lastname': 'bar'},
// {'fname': 'test', 'lastname': 'example'},
// {'fname': 'lorem', 'lastname': 'ipsum'},
// {'fname': 'new name 0', 'lastname': 'new last name 0'},
// {'fname': 'new name 1', 'lastname': 'new last name 1'},
// {'fname': 'new name 2', 'lastname': 'new last name 2'},
// ]
I have a list of product objects, it look like this:
Product Object
(
[id:private] => 1688115
[categoryId:private] => 1
[merchant:private] => theredshop
[name:private] => Pepsi Max Cans 6 x 375mL
)
every fetch data, i fetch 15 record (Im using using ElasticSearch), for the 15 record the product order is by merchant name, so it will be 1 merchant stacked on top, then goes to next merchant.
What i want to do is to 'shuffle' the object result order to at least 1 merchant shows once then put another merchant next. for example, here my current result:
merchant name
theredshop pepsi
theredshop lorem
theredshop ipsum
what i want is
merchant name
theredshop pepsi
sevel lorem
bluecircle ipsum
I know how to arrange the result by looping and checking the merchant name that has been loaded. but how can i re arrange the object result back? or should i just recreate the object?
Assuming a record table $products it can be written in PHP like that:
// restructure array as merchants having nested record sets
$merchants = [];
foreach(array_unique(array_column($products, 'merchant')) as $merchant)
$merchants[$merchant] = array_values(array_filter($products, function($v)use($merchant){ return $v->merchant === $merchant;}));
// itererate over indexes up do max. products per merchant and a add a product of
// each merchant having a record with that index
$max_count = max(array_map(function($v){return count($v);}, $merchants));
$new_order = [];
for($i = 0; $i<$max_count; $i++)
foreach ($merchants as $merchant)
if($item = $merchant[$i] ?? false)
$new_order[] = $item;
var_dump($new_order);
According to your comments you seem to have an object which you called "list" similar like that:
$products_object = (object)
[
(object)[
'merchant' => 'theredshop',
'name' => 'pepsi',
],
(object)[
'merchant' => 'sevel',
'name' => 'pepsi',
],
(object)[
'merchant' => 'sevel',
'name' => 'lorem',
],
(object)[
'merchant' => 'sevel',
'name' => 'ipsum',
],
(object)[
'merchant' => 'bluecircle',
'name' => 'ipsum',
],
];
Convert it into an array first in order to operate with array functions on it:
$products = (array) $products_object;
I have a probleme with a array.
In my array that has 15,000 rows, I have columns with associated names and values (sku).
I need to show all the names and make a separate on it if the sku is equal or not to the sku that is present on my product page
Exemple : array = [ 'code' => 'name1' ,
'sku' => '123456',
'code' => 'name1',
'sku' => '456789',
'code' => 'name2',
'sku' => '4565999']
etc ..........
if sku equals sku or not in my page product, i want to show the code with distinct on this .
First you need an array of arrays structure like this:
$arr = [
[ 'code' => 'name1', 'sku' => '123456' ],
[ 'code' => 'name2', 'sku' => '456789' ],
[ 'code' => 'name3', 'sku' => '4565999' ],
.
.
.
Then you can filter your array like this:
$existing_items_on_array = array_filter($arr,
function($item) use ($existing_items_on_page){
return array_search($item["sku"], $existing_items_on_page) !== false;
});
Or better (you still need to structure an array like on first solution):
I assume your SKU's are unique. Why not make them array keys?
$item_codes = [];
foreach($arr as $item){
$item_codes[$item["sku"]] = $item["code"];
}
then you would be accessing any element's code like this:
echo $item_codes[$product["sku"]]
I have 2 models that I want to populate by a CVS import. The first model is a list of Retail Stores and the second model is the Retail Stores corresponding locations.
This is the CSV import:
name,email,website,street_number,street_address,city,country,postcode,latitude,longitude
"Example name",info#example.com,10,"random street",amsterdam,netherlands,4000,52.666,4.3333
The RetailStores.php model will need these values:
name,
email,
website
The LocationStores.php model will need these values:
street_number,
street_address,
city,
country,
postcode,
latitude,
longitude
I will extract the data from the CSV file inside a foreach loop and attaching them to an empty array variable, from here will use some Eloquent to populate the database. Below is how I do this:
$file = Input::file('csv_file');
$data = $this->retailer->processCsv($file);
$retailers = [];
$locations = [];
foreach ($data as $value) {
$retailers[] = array(
'user_id' => Auth::user()->id,
'name' => $value['name'],
'email' => $value['email'],
'website' => $value['website'],
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
);
$locations[] = array(
'retailer_id' => $value['retailer_id'], // ISSUE HERE
'street_number' => $value['street_number'],
'street_address' => $value['street_address'],
'city' => $value['city'],
'state' => $value['state'],
'country' => $value['country'],
'country_code' => $value['country_code'],
'postcode' => $value['postcode'],
'latitude' => $value['latitude'],
'longitude' => $value['longitude'],
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
);
Retailer::insert($retailers);
Location::insert($locations);
}
As noted above I have 2 separate models the Retailers and Locations. I need to reference the Retailer ID in the $locations array. For now I have one option which is to have users enter the relevant retailer store id for each location in the CSV file, but people are well.... you know.
However considering that the CSV file will supply a "Store Name" for each location it has, is there not a way to reference an increment ID for each unique store name within the array? for example if the CSV table had these values:
Fruit,info#fruit.com,www.fruit.com,1,"apple street",etc
Fruit,info#fruit.com,www.fruit.com,120,"pear parkway",etc
Fruit,info#fruit.com,www.fruit.com,350,"orange avenue",etc
Meat,info#meat.com,www.meat.com,33,"Steak street",etc
Meat,info#meat.com,www.meat.com,33,"Chicken Road",etc
When getting these values within the foreach loop, is there a way one could give an increment ID for each of the repeated Store names which would thus reference the relevant store to its location?
Any advice, greatly appreciated.
You could store the retailer name in a way where it's easy to check if a particular name is in the retailer array already, and grab the ID out if it is. Something like this:
foreach ($data as $value) {
$retailer_name = $value['name']; // for clarity
// is the retailer name in the retailers array already?
if (isset($retailers[$retailer_name])){
// get the ID
$retailer_id = $retailers[$retailer_name]['user_id'];
} else { // otherwise add a new one
$retailer_id = Auth::user()->id; //store the ID for use in Locations
// use retailer name for the key of the array, so it's easily findable later
$retailers[$retailer_name] = array(
'user_id' => $retailer_id,
'name' => $value['name'],
'email' => $value['email'],
'website' => $value['website'],
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
);
}
$locations[] = array(
'retailer_id' => $retailer_id, // add either the new or existing ID
'street_number' => $value['street_number'],
'street_address' => $value['street_address'],
'city' => $value['city'],
'state' => $value['state'],
'country' => $value['country'],
'country_code' => $value['country_code'],
'postcode' => $value['postcode'],
'latitude' => $value['latitude'],
'longitude' => $value['longitude'],
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
);
Retailer::insert($retailers);
Location::insert($locations);
}
You then have an array with strings as keys for $retailers, though, and if that's a problem for insertion, you'll have to make a separate array for retailers or change it to numeric keys before you insert.