I am working with migration and I am migrating taxonomy terms that the document has been tagged with. The terms are in the document are separated by commas. so far I have managed to separate each term and place it into an array like so:
public function prepareRow($row) {
$terms = explode(",", $row->np_tax_terms);
foreach ($terms as $key => $value) {
$terms[$key] = trim($value);
}
var_dump($terms);
exit;
}
This gives me the following result when I dump it in the terminal:
array(2) {
[0]=>
string(7) "Smoking"
[1]=>
string(23) "Not Smoking"
}
Now I have two fields field_one and field_two and I want to place the value 0 of the array into field_one and value 1 into field_two
e.g
field_one=[0]$terms;
I know this isn't correct and I'm not sure how to do this part. Any suggestions on how to do this please?
If you are only looking to store the string value of the taxonomy term into a different field of a node, then the following code should do the trick:
$node->field_one['und'][0]['value'] = $terms[0];
$node->field_two['und'][0]['value'] = $terms[1];
node_save($node);
Note you will need to load the node first, if you need help with that, comment here and will update my answer.
You are asking specifically about ArrayList and HashMap, but I think to fully understand what is going on you have to understand the Collections framework. So an ArrayList implements the List interface and a HashMap implements the Map interface.
List:
An ordered collection (also known as a sequence). The user of this interface has precise control over where in the list each element is inserted. The user can access elements by their integer index (position in the list), and search for elements in the list.
Map:
An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
So as other answers have discussed, the list interface (ArrayList) is an ordered collection of objects that you access using an index, much like an array (well in the case of ArrayList, as the name suggests, it is just an array in the background, but a lot of the details of dealing with the array are handled for you). You would use an ArrayList when you want to keep things in sorted order (the order they are added, or indeed the position within the list that you specify when you add the object).
A Map on the other hand takes one object and uses that as a key (index) to another object (the value). So lets say you have objects which have unique IDs, and you know you are going to want to access these objects by ID at some point, the Map will make this very easy on you (and quicker/more efficient). The HashMap implementation uses the hash value of the key object to locate where it is stored, so there is no guarentee of the order of the values anymore.
You might like to try:
list($field_one, $field_two) = prepareRow($row);
The list function maps entries in an array (in order) to the variables passed by reference.
This is a little fragile, but should work so long as you know you'll have at least two items in your prepareRow result.
Related
I know my title is quite ambivalent but if you bear me, you'll find it is not so bad :P
I have a class method that gets quite different database fields in any order and builds an array based on those fields (each key adds another level into the array).
Now, that's the easy part. I also have a correction function that unifies the e.g. costs by some demographic data. The problem is that I need to address the right level in the correction formula.
I try to make an example:
I ask fields A,year,B,C,D and my correction formula for D depends on the year and C. I have formalized so that C and D are always the last ones to list but the problem is that how do I address the year so that I could get out an answer like [A][year][B]=function(year,c,d). The fields are in an array ($retr['fields']=array("A","year","B","C") (the result D comes automatically)
I tried to use foreach like
$retr['fields']=array("A","year","B","C")
$temp=get_data($retr);
foreach($temp as $${$retr['fields'][0]} => $yd)
foreach ($yd as $${$retr['fields'][1]} => $cd) {
$output[$${$retr['fields'][0]}][$${$retr['fields'][1]}]=0;
foreach ($cd as $a => $v)
$output[$${$retr['fields'][0]}][$${$retr['fields'][1]}]+=$v*$act[$year][$a]
and so on, but it seems that one can't use a variable variable as a key in foreach (or then I have got the syntax wrong). As now it just says that "Undefined variable: year"
Do you have any ideas how to express what I need?
Well I solved it, or rather not solved but programmed around.
For each foreach I checked the corresponding field and if it was year, I made a variable with value of current foreach key and referenced it with $$variable.
Like this:
$temp=get_data($retr);
foreach($temp as $varA => $yd) {
if ($retr[0]=="year")
$year_var=varA;
.
.
.
$output[$varA][$varB]+=$v*$act[$$year_var][$a]
I still would have preferred a cleaner solution but given my timeframe (or rather the loss of it) this should suffice.
I'm still interested in the "perfect solution"(TM)
Thx anyway :)
It's kind of hard to understand your structure, but it appears you're fetching some data items and then categorize them into tree-like structure.
In this case, even though a particular attribute (e.g. year) appears on some upper level it's still, essentially, an attribute of the data item itself, so keep it as such: convert the "value" into a non-scalar (either object or hash). Then you would be able to work with those attributes without referencing outer loop values (and without resorting to variable variables):
foreach($arr as $subarr) {
foreach ($subarr as $subsubarr) {
// ... and so on
foreach ($lastlevel as $value) {
$adjusted = correctionFunc($value->data, $value->year, $value->somethingelse); // assuming value is an object
}
}
}
I have an Array of product types in PHP, it looks pretty much like this:
$types = [
0 => "cars",
1 => "motorbikes",
2 => "boats",
3 => "airplanes"
];
So that when then user wants to get or save it, I can use the ID of the category to insert or get it from the database, like this:
select * from items where type = 0;
now, My doubt is the following: if I am using integer index keys, would it not be the same to use the following?
$types = ["cars", "motorbikes", "etc."];
Since PHP will give an integer auto-ordering.
Which one would you consider to be best practice in this case? The advantage of the first example seems to only be the fact that I can assign different keys, like for private categories or such, but I don't know really.
It is also important to consider that the values will need to be translated so, should I consider even just using IDs? like
$types = ["t1", "t2", "etc."];
and then insert the translation somewhere else?
There are 2 possible options.
Your current option 1 with manually set indexes.
A way better one - a table in the DB, holding these categories, which allow editing categories without losing the association between keys and names.
Your current option 2 is not an option at all - it will break the order the same moment you insert or delete a category
Here you set the index:
$types = [
3 => "airplanes"
index ^ ^ value
So, if you delete cars from the list, the index remain associated with it's value:
$types = [
1 => "motorbikes",
2 => "boats",
3 => "airplanes"
];
While if you don't set indexes manually
$types = ["motorbikes", "boats", "airplanes"];
airplanes will lose it's association, and become boats. It's not ht magic we expect from the web application
It all depends on the project. If I'm working with an array of items from the database I like the key to be the id from the database so it's available should I need it. If there's no need for the ids then there is no need to define a key. It will start at 0 anyways.
I think your first approach is a good one. You could even do it as default translation:
$types["en"] = []
Of course if you have a default language variable, you can use it from the start, and it will be much easier in the future to translate it further and expand
The arrays will be seen as the same so you can order it and take key as ID but it's not the best practice, all depends on how you design your relationship between arrays, php and database.
I might be missing your question but the array in PHP is ordered hash map basically. So ["cars", "motorcycles", "etc."] is guaranteed to preserver ordering (and have keys 0, 1, 2). But you might instead consider do the following
class AutoTypes {
const TYPE_CAR = 0;
const TYPE_MOTORCYCLE = 1;
const TYPE_BOAT = 2;
public static function getLabels() {
return array(self::TYPE_CAR => 'Car', self::TYPE_MOTORCYCLE => 'Motorcycle', self::TYPE_BOAT => 'Boat');
}
}
This way you can refer to the auto type by AutoTypes::CONSTANT. Because if you want to remove motorcycle at some point, not using clear indexes in the array, removing an item will brake your logic.
In my opinion, in this circumstance it's better to use
$types = ["cars", "motorbikes", "etc."];
As you say, PHP automatically assigns integer indexes starting from 0; so there's no need to specify the index that it would be assigned anyway.
It's up to you however, if you feel that it isn't clear enough just to declare an array without specifying the indexes manually then that's up to you. But personally I feel that it's obvious to any competent programmer and so therefore it's a waste of time and hard disk space to manually specify those indexes.
I am trying to access elements from a multidimensional array in an object. For example, let's assume there is some class Foo that has a variable called $phone that represents the multidimensional array.
$phone -> structure will look like
Array {
"home" Array(1) {[0] = "555-1212"},
"work" Array(2) {[0] = "555-1234", [1] = "555=5434"},
"other" Array(1) {[0] = "555=9090"}
}
Note: We can't assume we know the keys.
I can access a value by giving explicit keys, i.e.,
$foo->phone["home"][0]
The problem comes to when I don't explicitly know the keys and pull them from elsewhere.
For example if $type="phone", $subtype = "home", and I want the first entry I would expect to use:
$object->$type[$subtype][0]
to get the value, but I get an error and it doesn't think it is an array. I am not sure where the error is.
The next thing would be to add elements to the lowest level array. I assume the following would work, but doesn't:
array_push($object->$type[$subtype], $value)
This mutidimensional array would allow me to store phone numbers labelled by keys in a single nested structure. If this is overcomplicating the issue please let me know. The reason I chose this structure is because the keys can be anything the user customizes.
Thanks.
I believe this will work if you save $object->$type as it's own variable, then access that variable to go deeper in the array.
I need to create an association between an Array and a Number; as PHP lacks a Map type, I am trying using an array to achieve this:
$rowNumberbyRow = array();
$rowNumberByRow[$rowData] = $rowNumber;
However, when I evaluate the code, I get the following Error:
Warning: Illegal offset type
Just to note, the data stored in the array ($rowData) does not have any 'unique' values that I can use as a key for the $rowNumberByRow Array.
Thanks!
UPDATE:
To answer some of my commenters, I am trying to create a lookup table so that my application can find the row number for a given row in O(1) time.
PHP does have a map Class: It's called SplObjectStorage. It can be accessed with exactly the same syntax as a general array is (see Example #2 on the reference).
But to use the class you will have to use the ArrayObject class instead of arrays. It is handled exactly the same way arrays are and you can construct instances from arrays (e.g. $arrayObject = new ArrayObject($array)).
If you don't want to use those classes, you can also just create a function that creates unique hash-strings for your indexes. For example:
function myHash($array){
return implode('|',$array);
}
$rowNumberByRow[myHash($array)] = $rowNumber;
You will of course have to make sure that your hashes are indeed unique, and I would strongly suggest you use the SplObjectStorage and maybe read a little bit more about the SPL classes of php.
Why not just store the row number in the array? e.g:
$rowData['rowNumber'] = $rowNumber;
You could instead serialize the array, e.g:
$rowNumberByRow[serialize($rowData)] = $rowNumber;
However that's pretty inefficient.
In php you can use only scalar values as an array keys.
If your $rowNumber is unique - then you'd try to use the opposite relation direction. If it is not unique - then you don't have any possible solution I know.
The answer has been alredy given and accepted, but while i was searching for a similar problem, i found this question, and i felt like i should drop a line: when someone wants to use an array with values as keys for another array, it would be useful to use the function array_combine.
If i got the arrays correctly, you could use:
$rowNumberByRow = array_combine($rowData, $rowNumber);
Please take a look at the PHP manual to see some info about permitted values for the keys :)
I have a class (say Product) with a property (say product_id) and has methods to retrieve information from multiple database tables for given product ID. Now I want the class methods to handle one product ID as well as an array of product IDs (in order to save the number of queries). Also the output will vary depending on the input i.e. for array as input, I'll have as output an array indexed with product ids, whereas for a single ID, I might not need this array.
What is the clean way to design such a class?
Here are a couple of things I've thought of:
Have separate methods with indicative names for single and multiple ids (clean but duplication)
Have only one method for both types of input, check input type...process...format output as per the input (not really clean)
Internally, always work with an array of values. If there's only one value in the array, so be it, but that doesn't need to change your logic at all.
For input/output, you may want to make your methods accept a single value, which you're going to turn into an array:
public function foo($val) {
$val = (array)$val;
...
}
And/or, you might create a "singular convenience wrapper" that just makes it clear that it returns or accepts single results:
public function foos(array $vals) {
...
return /* array of elements */;
}
public function foo($val) {
return current($this->foos(array($val)));
}