I have an array that looks like this:
Id = "ADA001"
Stock: 15
The array has about 1700 records that looks the same, how would I search the array for the ID 1 and return the stock?
Edit: I will need to access the stock of each one of these 17000 records
Edit: I have been getting some help from Daniel Centore, he told me to set an arrays primary key to the id of the item and that it is equal to the stock, but I can't get it to work.
I am currently getting the data from an MySQL database and I store it in an array, like so:
$data[] = array();
$getdisposabletest = mysqli_query($connect, "Select id, disposable FROM products");
while ($z = mysqli_fetch_array($getdisposabletest)) {
$data = $z;
}
Now when I use Daniels code that looks like this:
$myMap = [];
foreach($data as $item) {
$myMap[$item['id']] = $item['disposable'];
}
It doesn't return anything when I try to echo my product with the ID "ADA001"
echo $myMap["ADA001"];
Also when I do "count($mymap)" it says its 2 records big, when it should be muuuch larger than that?
Thanks for help
I would use array_filter. Return the result of a comparitor.
$results = array_filter($targetArray, function($el) {
return $el === 1;
});
Edit: Now that it has been made clear that the OP wants to query from thousands of items, the correct way to do this is to make the Id the key to a map in PHP, like this:
$myMap = [];
foreach($array as $item) {
$myMap[$item['Id']] = $item['Stock'];
}
Now, whenever you want to access item '12', simply use $myMap['12'].
The reason this is faster is because of something called algorithmic complexity. You should read about Big-O notation for more info. Essentially, the first operation here is on the order of n and then looping through each of the items that comes out is on the order of n*log(n), so the final result is on the order of n*log(n) which is the best you'll be able to do without more information. However, if you were only accessing one element, just accessing that one element via MySQL would be better because it would be on the order of log(n), which is faster.
Edit 2: Also notice that if you were to access mutliple fields (ie not just the stock) you could do the following:
$myMap = [];
foreach($array as $item) {
$myMap[$item['Id']] = $item;
}
And simply access item 12's stock like this: $myMap['12']['stock'] or its name like this: $myMap['12']['name'].
You would do something like this.
$newArray=[];
foreach($array as $item){
if($item['Id'] === 1){
$newArray[] = $item;
}
}
$stockArray = array_column($newArray,'Stock');
Related
I am trying to create a multidimensional array at run-time that queries and stores several MySQL results. For instance, let us say we have a table like so (is fictional, so please don't pick at the example):
**store--tag--color--size**
1--101--blue--s
2--102--red--s
2--103--yellow -- m
3--104--blue--m
The need is to create an multi-d array that will store all the products per store. The result I would like is:
$storeArray = array[[[101],[blue],[s]],[[102,103],[red,yellow],[s,m]],[[104],[blue],[m]]];
here is the code I have:
$counter = 0;
foreach($storeIDs as $item){
$result = mysql_query('select whatever');
$rows = mysql_num_rows($result);
for($i=0;$i<$rows;$i++){
$tag[$i] = mysql_result();
$color[$i] = mysql_result();
$size[$i] = mysql_result();
}
$tempArray = array($tag,$,$color,$size);
$storeArray[$counter] = $tempArray;
unset($tempArray);
$counter++;
}
The problem is, even though I have unset $tempArray, the third loop which should capture just
[[104],[blue],[m]]
actually stores
[[104,103],[blue,yellow],[m,m]].
I've tried setting $tempArray to array(), or array(array()). The data from the second loop always spills over into ANY future iteration that is of smaller size.
How can I get $storeArray to look like the goal above?
Thank you
You're unsetting $tmpArray, but it looks like you may need to also unset $tag, $color, and $size as well. There are better approaches with a slightly different data structure, but as is, have you tried this?
unset($tempArray,$tag,$color,$size);
Effectively, you might set $tag[0] and $tag[1] in a loop that has two items. Then, for a loop that has one item you update $tag[0], but $tag[1] remains set.
If you have any array $p that you populated in a loop like so:
$p[] = array( "id"=>$id, "Name"=>$name);
What's the fastest way to search for John in the Name key, and if found, return the $p index? Is there a way other than looping through $p?
I have up to 5000 names to find in $p, and $p can also potentially contain 5000 rows. Currently I loop through $p looking for each name, and if found, parse it (and add it to another array), splice the row out of $p, and break 1, ready to start searching for the next of the 5000 names.
I was wondering if there if a faster way to get the index rather than looping through $p eg an isset type way?
Thanks for taking a look guys.
Okay so as I see this problem, you have unique ids, but the names may not be unique.
You could initialize the array as:
array($id=>$name);
And your searches can be like:
array_search($name,$arr);
This will work very well as native method of finding a needle in a haystack will have a better implementation than your own implementation.
e.g.
$id = 2;
$name= 'Sunny';
$arr = array($id=>$name);
echo array_search($name,$arr);
Echoes 2
The major advantage in this method would be code readability.
If you know that you are going to need to perform many of these types of search within the same request then you can create an index array from them. This will loop through the array once per index you need to create.
$piName = array();
foreach ($p as $k=>$v)
{
$piName[$v['Name']] = $k;
}
If you only need to perform one or two searches per page then consider moving the array into an external database, and creating the index there.
$index = 0;
$search_for = 'John';
$result = array_reduce($p, function($r, $v) use (&$index, $search_for) {
if($v['Name'] == $search_for) {
$r[] = $index;
}
++$index;
return $r;
});
$result will contain all the indices of elements in $p where the element with key Name had the value John. (This of course only works for an array that is indexed numerically beginning with 0 and has no “holes” in the index.)
Edit: Possibly even easier to just use array_filter, but that will not return the indices only, but all array element where Name equals John – but indices will be preserved:
$result2 = array_filter($p, function($elem) {
return $elem["Name"] == "John" ? true : false;
});
var_dump($result2);
What suits your needs better, resp. which one is maybe faster, is for you to figure out.
I have a controller function in CodeIgniter that looks like this:
$perm = $this->job_m->getIdByGroup();
foreach($perm as $pe=>$p)
{
$pId = $p['id'];
$result = $this->job_m->getDatapermission($pId);
}
$data['permission'] = $result;
What I need to do is list the data in the result in the view, but I get only the last value while using this method. How can I pass all the results to the view?
Store it in an array. Like this:
foreach($perm as $pe=>$p){
$result[] = $this->job_m->getDatapermission($p['id']);
}
Because $result is not an array...
try this:
$result=array();
foreach($perm as $pe=>$p)
{
$pId = $p['id'];
$result[] = $this->job_m->getDatapermission($pId);
}
$data['permission'] = $result;
Note:
My answer uses a counter to enable the display of a single group result when needed.
Guessing from your need to loop and display the value of $result, possibly, it is an array or object returned by $query->result(). Things could be a bit complex.
Example: if $perm is an array of 5 items( or groups), the counter assigns keys 1 - 5 instead of 0 - 4 as would [] which could be misleading. Using the first view example, you could choose to display a single group value if you wants by passing it via a url segment. Making the code more flexible and reusable. E.g. You want to show just returns for group 2, in my example, $result[2] would do just that else next code runs. See my comments in the code.
$perm = $this->job_m->getIdByGroup();
$counter = 1;
foreach($perm as $pe=>$p)
{
$pId = $p['id'];
$result[$counter] = $this->job_m->getDatapermission($pId);
$counter++;
}
$data['permission'] = $result;
As mentioned above Note:
I Added a Counter or Key so you target specific level. If the groups are:
Men, Women, Boys, Girls, Children; you'd know women is group two(2) If you desire to display values for just that group, you don't need to rewrite the code below. Just pass the group key would be as easy as telling it by their sequence. To display all the loop without restrictions, use the second view example. To use both, use an if statement for that.
###To access it you could target a specific level like
if(isset($permission)){
foreach($permission[2] as $key => $value){
echo $value->columnname;
}
###To get all results:
foreach($permission as $array){
foreach($array as $key => $value){
echo $value->columnname;
}
}
}
I'm using ThumbsUp V2 Voting Script and i'm trying to display the posts based on the number of votes:
<?php $items = ThumbsUp::items()->orderby('votes_total')->get() ?>
The values are stored in mysql so i thought of:
$display = mysql_query("SELECT * FROM banat");
$items = ThumbsUp::items($display)->orderby('votes_total')->get() ;
But i thik i've definitely done this wrong since it's just displaying an output:
Array
If you get an array, you must loop on it to show the data. You cannot just do an echo on a var that is an array. You should have something like this:
foreach($items as $item)
{
echo $item;
}
Your $items is an array, and I assumed you attempted to
echo $items;
Instead you will need to loop over it:
foreach ($items as $item) {
// View the structure of `$item`
print_r($item);
}
If you only expect $items to hold one thing, then just do:
print_r($items[0]);
I have the following array:
$masterlist=[$companies][$fieldsofcompany][0][$number]
The third dimension only exists if the field selected from $fieldsofcompany = position 2 which contains the numbers array. Other positions contain regular variables. The 3rd dimension is always 0 (the numbers array) or Null. Position 4 contains numbers.
I want to cycle through all companies and remove from the $masterlist all companies which contain duplicate numbers.
My current implementation is this code:
for($i=0;$i<count($masterlist);$i++)
{
if($masterlist[$i][2][0][0] != null)
$id = $masterlist[$i][0];
for($j=0;$j<count($masterlist[$i][2][0]);$j++)
{
$number = $masterlist[$i][2][0][$j];
$query = "INSERT INTO numbers VALUES('$id','$number')";
mysql_query($query);
}
}
Which inserts numbers and associated IDs into a table. I then select unique numbers like so:
SELECT ID,number
FROM numbers
GROUP BY number
HAVING (COUNT(number)=1)
This strikes me as incredibly brain-dead. My question is what is the best way to do this? I'm not looking for code per se, but approaches to the problem. For those of you who have read this far, thank you.
For starters, you should prune the data before sticking it into the database.
Keep a look up table that keeps track of the 'number'.
If the number is not in the look up table then use it and mark it, otherwise if its in the look up table you can ignore it.
Using an array for the look up table and with keys being the 'number' you can use the isset function to test if the number has appeared before or not.
Example pseudo code:
if(!isset($lookupTable[$number])){
$lookupTable[$number]=1;
//...Insert into database...
}
Now that I think I understand what you really want, you might want to stick with your two-pass approach but skip the MySQL detour.
In the first pass, gather numbers and duplicate companies:
$duplicate_companies = array();
$number_map = array();
foreach ($masterlist as $index => $company)
{
if ($company[2][0][0] === null)
continue;
foreach ($company[2][0] as $number)
{
if (!isset($number_map[$number])
{
// We have not seen this number before, associate it
// with the first company index.
$number_map[$number] = $index;
}
else
{
// Both the current company and the one with the index stored
// in $number_map[$number] are duplicates.
$duplicate_companies[] = $index;
$duplicate_companies[] = $number_map[$number];
}
}
}
In the second pass, remove the duplicates we have found from the master list:
foreach (array_unique($duplicate_companies) as $index)
{
unset($masterlist[$index]);
}