Say that I have an associative array of different types of fruits in baskets and the amount in each basket ('Banana'=>50 and etc) and I need to know how many of each type of fruit there is, but I don't know the possible types of fruit before I start the loop that generates the array. This may result in duplicate entries such as:
$baskets = array(
"Apple"=>"35",
"Banana"=>"37",
"Apple"=>"43"
);
Question A: Is it even possible to make the second "Apple" entry or will it result in an error?
The answer was: Not possible, it would overwrite the first one with 43
Question B1: Assuming that the answer to A is "It's possible", how do I merge the two so that $baskets becomes ("Apple"=>"78","Banana"=>"37")?
Question B2: Assuming that the answer to A is "Not possible", how do I go about figuring out if there's already apples in the array and add the amount to the entry rather than attempting to add it as a new point in the array?
An answer to B2 will obviously make B1 obsolete even if A is "possible".
If neither B1 nor B2 are possible, then is there some other way that I can keep track of the amount of each type of fruit as I loop through the baskets?
Thanks for all of the helpful answers.
Q A: No
Q B:
if(isset($baskets["apple"]))
{
$baskets["apple"] = $baskets["apple"] + VALUE
}
You will never get the duplicate keys in an array, there can only be unique keys. You will be only overwriting values for the key of duplicate fruits.
Answer B: due to the reason mentioned above, you will have to check in your loop whether the key exists in your resulting array, and if it does, add the new value to the existing one, otherwise store the value under this key.
Answer to B1: see answer to A.
Answer to B2: array_key_exists or isset
The algorithm depends on the way your data is stored. Maybe there's a more clever way possible.
Question A: Is it even possible to make the second "Apple" entry or will it result in an error?
No, would it be so hard to try it out?
$basket['apple']=35;
$basket['apple']=43;
print $basket['apple']; // the output will be 43
The second assignment overwrites the former.
how do I merge the two
You could simply do this:
$basket['apple']+=35;
$basket['apple']+=43;
print $basket['apple'];
The problem with this is that the first time you reference an entry in the array, a PHP warning will be triggerred as it does not yet exist. While you should have your error reporting disabled (but error logging enabled) on your production system, this causes performance and support issues, hence a better solution is....
function add_to($basket, $product, $amount)
{
if (isset($basket[$product])) {
$basket[$product]+=$amount;
} else {
$basket[$product]=$amount;
}
}
add_to($basket, 'apple', 35);
add_to($basket, 'apple', 43);
print $basket['apple']; // output will be 78
It is not possible to have the same key ('Apple') more then once in an associative array. If you are looping through and come across 'Apple' twice, the second entry will override the first:
array['Apple'] = 35
array['Banana']= 37
array['Apple' = 43
would result in an array:
( 'Apple' => 43, 'Banana' = 37 )
See Labradorcode's answer for the correct implementation and don't forget to cast your string values as ints!
EDIT to elaborate on his answer
for($i = 0; i < count(list_of_fruits){
if(!array_key_exists($fruit, $basket){
$basket[$fruit] = 0;
}
$basket[$fruit] = $basket[$fruit] + (int)$num_fruits;
something like that
Related
I'm trying to count a php array.
I have my code successfully counting it, but the value is returning one digit higher than what my array is.
I have tried using -- when echoing my array, but that doesn't work.
Here is my code so far:
$quotes[0] = "Volvo";
$quotes[1] = "BMW";
$quotes[2] = "Toyota";
$quotesCount = count($quotes);
echo ($quotes[rand(0, 2)]);
echo $quotesCount--;
When it count's it returns "3" which makes sense because there are three items, but how do I subtract a number when it echos so that it reflects the the largest digit in the array?
What you tried with the echo $quotesCount--; is almost doing what you want it to. What you missed though is how the -- works. You can place it either infront of the variable or behind it - and that makes a difference.
To get the full version, read this: http://php.net/manual/en/language.operators.increment.php
But the short version is that you could potentially do this:
echo --$quotesCount;
Which will show you the value you want.
However this is still not really true - you are confusing array keys with the count of elements in an array.
If your array had non-sequential keys (1,3,5) for example, that code would return 2 - which is certainly not the highest key.
You can get a nice stepping stone to the key itself by using http://php.net/manual/en/function.array-keys.php - then you can reference the actual key itself by its order in the array.
You can use array_max($quotes) z this will return the highest key in the array.
Hey" you should array_max($array) in this case.
array_max is an array function which returns the highest value of an array.
That's it,
Keep Coding :)
In my application there are different promotions and usera can answer to that promotions using single or multi choice questions. I am using following logic and it works fine except one problem:
for ($i=0;$i<count($questions);$i++)
{
if($questions[$i][type_of_question] == 'multiple_choice')
{
$options_array = explode(",", $_REQUEST["que".$questions[$i][id]]);
}
// Code here which insert answers in database table
}
This line of code:
$options_array = explode(",", $_REQUEST["que".$questions[$i][id]]);
this code shows comma seperated answers of the questions. For example:
Example 1: test1,test2,test3 [This scenario works fine]
Example 2: yes,no,I am not interested(cricket,footbal)
Example 2 has shows the problem e.g. if there is , inside the choice option. Php explode function break and values according to , so in this case I gets 4 array elements.
Array[0] => yes
Array[1] => no
Array[3] => I am not interested(cricket
Array[4] => footbal
while I required following:
Array[0] => yes
Array[1] => no
Array[3] => I am not interested(cricket,footbal)
How can I fix this problem? Any suggestion?
You need to fix the way the data is being fed in from the front-end: there's no way in this code alone to fix this problem. For example, you could have the input yes, no, maybe, and it could be either yes, no, maybe, or yes, no, maybe.
You need to perform some consistent encoding or escaping on the front-end so you can uniquely access the records. You haven't told us how it's submitted on the front, but just joining the answers together with commas won't be enough. You could try escaping the commas in the fields!
I have PHP $_SESSION arrays that have an undefined amount of elements. Is it possible to initialise all the values to 0, or do I have to check whether the value is NULL and then set to 0 every time I check a value?
Edit: I'm sorry for the vagueness of my question.
I have an undefined amount of levels, and I'd like to store all the scores of each level in that array. Currently my amount of levels is fixed, so I am currently just writing:
$_SESSION['totals'] = array(0,0,0,0,0);
And then when adding manipulating the data, I simply increment/add a certain amount to that element.
Now I'd prefer to have the same ease of directly incrementing/adding values to certain elements without needing to check whether a value is NULL or something like that...
Edit 2: edited my code as follows:
$_SESSION['totals'] = array();
if(array_key_exists($row['level']-1,$_SESSION['totals'])){
$_SESSION['totals'][$row['level']-1]++;
}else{
$_SESSION['totals'][$row['level']-1] = 1;
}
And it seems to work. Thanks fellas!
You can use array_fill_keys function to fill an array with specified value for defined keys:
$keys = array('foo', 'bar', 'baz');
$output = array_fill_keys($keys, 0);
Defining an array with initial values is defining an array with a length. This does not prevent you from adding or removing elements from the array:
// initial array
$myArray = [0, 0, 0, 0];
print_r($myArray); // would output Array ( [0] => 0 [1] => 0 [2] => 0 [3] => 0)
$myArray[] = 1;
print_r($myArray); // would output Array ( [0] => 0 [1] => 0 [2] => 0 [3] => 0 [4] => 1 )
$_SESSION contains only what you put into it. Just make sure you add 0 instead of null the first time you add something.
If you need to do this later, I think your design might be bad. But anyway, $_SESSION is like a normal array, so you can just use PHP's array function to traverse the array and check or change each value.
PHP arrays aren't really arrays you might know from other languages. They really are more like linked lists with hash access.
What this means is: You either know all the string array indices you want to use, and either make sure they exist, or you check their existence every time you access them which might fail.
For numeric indices, the same thing applies. You might have an array with indices 1, 2 and 4 present, but if you run over it with only a for loop, you will trigger a notice when accessing the nonexistant element 3.
Use foreach loops whenever you want to iterate arrays. Check with isset() whenever you want to document that the array value might not be present. Don't do it if you know or assume that the array element MUST be present - if not, you get the notice as a reminder that your code is working on a data structure that is NOT what you thought it is. Which actually is a good thing. Then fix it. :)
Your best bet would be to abstract your session stuff by creating facade methods, or getters and setters around the session variables rather than access them directly. This way you can return a default value if the one you're after doesn't exist.
I've used array_key_exists() to check if the index is set. If it is not, I display 0 or add store a certain value in that field, else I show the value of that index or add certain value to that field.
Credit to Sven for bringing that up.
to check what u have in your sessions, loop tru it. not sure if this is what u are asking.
foreach($_SESSION as $x=>$y)
{
if(empty($x)) { //do something }
}
There is an array, in PHP. It is setup like so
$array_var = array(array(1,2,3,4), array(5,6,7,8), array(3,5,3,9));
This array is from a csv file obtained using the fgetcsv function. If I was to echo out the array properly to display its contents I would make it so it shows like this:
field1 field2 field3 field4
1 2 3 4
5 6 7 8
3 5 3 9
etc etc..
Now I want to sort this array. But I want to sort only one of the columns in all of the arrays. Put another way, and for example, I want to take every third value in every array inside the main array and list them ascendingly, alphabetically. So for a specific case, we would take every value in field3, from the above table, and sort it. And also make it so that the end result of the sort will rearrange the columns so that they are correctly lined up with their values.
End result
field1 field2 field3 field4
1 2 3 4
3 5 3 9
5 6 7 8
etc etc..
How can this be accomplished?
The reason for the challenge is I am trying to remove duplicates from a single column in a csv file. I think the fastest way to do it is to sort the values and look for matches in range.
It's difficult to give you an exact answer since there are things you leave out from your explanation. For example, how should lines that are sorted by one of the columns but have differences in other columns be sorted internally? Should they be sorted by some other column, be left in the original order or could they be placed in an arbitrary order?
Given the way I interpret your question, I would probably define my own class for comparisons.
<?php
class ColumnCompare {
function __construct($column) {
$this->column = $column;
}
function compare($a, $b) {
if ($a[$this->column] == $b[$this->column]) {
return 0;
}
return ($a[$this->column] < $b[$this->column]) ? -1 : 1;
}
}
// Hard-coded input
$array_var = array(array(1,2,3,4), array(5,6,7,8), array(3,5,3,9));
$sort_by_col = 2;
// Create object for sorting by a particular column
$obj = new ColumnCompare($sort_by_col);
usort($array_var, array($obj, 'compare'));
// Write CSV to standard output
$sout = fopen('php://stdout', 'w');
foreach ($array_var as $fields) {
fputcsv($sout, $fields);
}
fclose($sout);
?>
In the end you pose another question, which is impossible to answer. If you remove duplicates from a single column, what is then supposed to happen with the rest of the line? Should only one line be kept, and in that case which one? You could also by "remove duplicates" mean that you want to remove the values and put NULL in their positions. If you want that particular problem solved, you need to provide some details.
If your CSV file is really simple, and all the values on any line with duplicates are identical (which was the case in your example before it was edited), you can easily run a command such as
sort myfile.csv | uniq
but I have a feeling that it's more complicated than that. uniq also has settings to return only the duplicate lines for example. It's also possible to write commands to retrieve a certain column from each line and operate on that. But like I said, it's not possible to construct such a command without more information.
I am paging through the elements of an array.
I get the total number of elements in the array with:
$total = count($myarray);
My paging function loads the current element on the page and provides "Previous" and "Next" links that have urls like:
http://myapp.com?page=34
If you click the link I grab that and load it onto the page by getting (I sanitize the $_GET, this is just for example):
$element = $myarray[$_GET['page']];
This should grab the element of the array with a key == $_GET['page'] and it does. However, the problem is that my total count of elements doesn't match some keys because while there are 100 elements in the array, certain numbers are missing so the 100th item actually has a key of 102.
How should I be doing this? Do I need to rewrite the keys to match the available number of elements? Some other method? Thanks for your input.
If you have gaps in the indices, you should reindex the array. You can do that before you generate the links, or probably easier on the receiving page:
$myarray = array_values($myarray);
$element = $myarray[$_GET['page']];
This would give you the 100th element, even if it previously had the key 102. (You could use a temporary array of course, if you need to retain the original indexing.)
you can use
$array = array_values($array);
How should I be doing this? Do I need
to rewrite the keys to match the
available number of elements? Some
other method?
No you don't need to worry about them not matching. Php arrays are associative containers, like dictionaries in other languages. If you define something at 98 and 100, 99 isn't sitting there in memory, the data structure behind the associative container only stores whats there. You're not wasting space by not "filling it up" up to count.
So the practice you describe is fine. If there is no page "99" nothing need show up in your array. It may be nice, however, to see that your array doesn't have anything for the 'page' parameter and display an error message.
But then why, when I access $total =
count($myarray); $myarray[$total]
where $total = 100 I do not get the
last element? I can put page=101 and
get one more record. I should not be
able to do this
Because count is counting how many things are in the array. If you have an array with only the even elements filled in, ie:
$myArray[0] = "This";
$myArray[2] = "is";
$myArray[4] = "even";
Here count($myArray) is 3. There's nothing in [1] or [3]. Maybe this is easier to see when you take numbers out of the equation. Arrays can have string indexes
$myArray = array();
$myArray["Hello"] = "A Bunch of";
$myArray["World"] = "words";
Here count($myArray) is 2.
In the first case, it wouldn't make sense to access $myArray[3] because nothing is there. Clearly in the second example, there's nothing at 2.