i have a multidimensional array:
$image_path = array('sm'=>$sm,'lg'=>$lg,'secondary'=>$sec_image);
witch looks like this:
[_media_path:protected] => Array
(
[main_thumb] => http://example.com/e4150.jpg
[main_large] => http://example.com/e4150.jpg
[secondary] => Array
(
[0] => http://example.com/e4150.jpg
[1] => http://example.com/e4150.jpg
[2] => http://example.com/e9243.jpg
[3] => http://example.com/e9244.jpg
)
)
and i would like to convert it into an object and retain the key names.
Any ideas?
Thanks
edit: $obj = (object)$image_path; doesn't seem to work. i need a different way of looping through the array and creating a object
A quick way to do this is:
$obj = json_decode(json_encode($array));
Explanation
json_encode($array) will convert the entire multi-dimensional array to a JSON string. (php.net/json_encode)
json_decode($string) will convert the JSON string to a stdClass object. If you pass in TRUE as a second argument to json_decode, you'll get an associative array back. (php.net/json_decode)
I don't think the performance here vs recursively going through the array and converting everything is very noticeable, although I'd like to see some benchmarks of this. It works, and it's not going to go away.
The best way would be to manage your data structure as an object from the start if you have the ability:
$a = (object) array( ... ); $a->prop = $value; //and so on
But the quickest way would be the approach supplied by #CharlieS, using json_decode(json_encode($a)).
You could also run the array through a recursive function to accomplish the same. I have not benchmarked this against the json approach but:
function convert_array_to_obj_recursive($a) {
if (is_array($a) ) {
foreach($a as $k => $v) {
if (is_integer($k)) {
// only need this if you want to keep the array indexes separate
// from the object notation: eg. $o->{1}
$a['index'][$k] = convert_array_to_obj_recursive($v);
}
else {
$a[$k] = convert_array_to_obj_recursive($v);
}
}
return (object) $a;
}
// else maintain the type of $a
return $a;
}
Hope that helps.
EDIT: json_encode + json_decode will create an object as desired. But, if the array was numerical or mixed indexes (eg. array('a', 'b', 'foo'=>'bar') ), you will not be able to reference the numerical indexes with object notation (eg. $o->1 or $o[1]). the above function places all the numerical indexes into the 'index' property, which is itself a numerical array. so, you would then be able to do $o->index[1]. This keeps the distinction of a converted array from a created object and leaves the option to merge objects that may have numerical properties.
Related
Take a look at the following code:
$a = json_decode('{"0":"xy"}', true);
This will return an associative array like [0 => "xy"].
Is there a way not to automatically convert the keys to numbers? The result I'd like to have would be the array ["0" => "xy"] with strings as keys exclusively.
First decode it as an object (without true parameter) and then typecast it as array:
$a = (array) json_decode('{"0":"xy"}');
var_dump($a);
Ouput:
array (size=1)
'0' => string 'xy' (length=2)
Not really sure why you would want numerical array keys to be strings. It can make life harder when trying to search through an array by key or rekey the array.
However, if you really want your keys to be strings this should help
$array = json_decode('{"0":"xy"}', true);
foreach($array as $key => $value) {
$newArray[(string) $key] = $value;
}
I have the following array, I'm trying to append the following ("","--") code
Array
(
[0] => Array
(
[Name] => Antarctica
)
)
Current JSON output
[{"Name":"Antarctica"}]
Desired output
{"":"--","Name":"Antarctica"}]
I have tried using the following:
$queue = array("Name", "Antarctica");
array_unshift($queue, "", "==");
But its not returning correct value.
Thank you
You can prepend by adding the original array to an array containing the values you wish to prepend
$queue = array("Name" => "Antarctica");
$prepend = array("" => "--");
$queue = $prepend + $queue;
You should be aware though that for values with the same key, the prepended value will overwrite the original value.
The translation of PHP Array to JSON generates a dictionary unless the array has only numeric keys, contiguous, starting from 0.
So in this case you can try with
$queue = array( 0 => array( "Name" => "Antarctica" ) );
$queue[0][""] = "--";
print json_encode($queue);
If you want to reverse the order of the elements (which is not really needed, since dictionaries are associative and unordered - any code relying on their being ordered in some specific way is potentially broken), you can use a sort function on $queue[0], or you can build a different array:
$newqueue = array(array("" => "--"));
$newqueue[0] += $queue[0];
which is equivalent to
$newqueue = array(array_merge(array("" => "--"), $queue[0]));
This last approach can be useful if you need to merge large arrays. The first approach is probably best if you need to only fine tune an array. But I haven't ran any performance tests.
Try this:
$queue = array(array("Name" => "Antarctica")); // Makes it multidimensional
array_unshift($queue, array("" => "--"));
Edit
Oops, just noticed OP wanted a Prepend, not an Append. His syntax was right, but we was missing the array("" => "--") in his unshift.
You can try this :
$queue = array("Name" => "Antarctica");
$result = array_merge(array("" => "=="), $queue);
var_dump(array_merge(array(""=>"--"), $arr));
So far all my research has shown that this cannot be achieved without writing lengthy functions such as the solution here
Surely there is a simpler way of achieving this using the predefined PHP functions?
Just to be clear, I am trying to do the following:
$test = array(
'bla' => 123,
'bla2' => 1234,
'bla3' => 12345
);
// Call some cool function here and return the array where the
// the element with key 'bla2' has been shifted to the beginning like so
print_r($test);
// Prints bla2=1234, bla=>123 etc...
I have looked at using the following functions but have so far have not been able to write a solution myself.
array_unshift
array_merge
To Summarize
I would like to:
Move an element to the beginning of an array
... whilst maintaining the associative array keys
This seems, funny, to me. But here ya go:
$test = array(
'bla' => 123,
'bla2' => 1234,
'bla3' => 12345
);
//store value of key we want to move
$tmp = $test['bla2'];
//now remove this from the original array
unset($test['bla2']);
//then create a new array with the requested index at the beginning
$new = array_merge(array('bla2' => $tmp), $test);
print_r($new);
Output looks like:
Array
(
[bla2] => 1234
[bla] => 123
[bla3] => 12345
)
You could turn this into a simple function that takes-in a key and an array, then outputs the newly sorted array.
UPDATE
I'm not sure why I didn't default to using uksort, but you can do this a bit cleaner:
$test = array(
'bla' => 123,
'bla2' => 1234,
'bla3' => 12345
);
//create a function to handle sorting by keys
function sortStuff($a, $b) {
if ($a === 'bla2') {
return -1;
}
return 1;
}
//sort by keys using user-defined function
uksort($test, 'sortStuff');
print_r($test);
This returns the same output as the code above.
This isn't strictly the answer to Ben's question (is that bad?) - but this is optimised for bringing a list of items to the top of the list.
/**
* Moves any values that exist in the crumb array to the top of values
* #param $values array of options with id as key
* #param $crumbs array of crumbs with id as key
* #return array
* #fixme - need to move to crumb Class
*/
public static function crumbsToTop($values, $crumbs) {
$top = array();
foreach ($crumbs AS $key => $crumb) {
if (isset($values[$key])) {
$top[$key] = $values[$key];
unset($values[$key]);
}
}
return $top + $values;
}
I'm trying to understand STD_PROP_LIST constant in the documentation but so far i didn´t understand it, and didn´t found any explanation :(
The documentation has the following example:
$a = new ArrayObject(array(), ArrayObject::STD_PROP_LIST);
$a['arr'] = 'array data';
$a->prop = 'prop data';
$b = new ArrayObject();
$b['arr'] = 'array data';
$b->prop = 'prop data';
// ArrayObject Object
// (
// [prop] => prop data
// )
print_r($a);
// ArrayObject Object
// (
// [arr] => array data
// )
print_r($b);
Both prints give me the same exact result:
ArrayObject Object ( [prop] => prop data [storage:ArrayObject:private] => Array ( [arr] => array data ) )
ArrayObject Object ( [prop] => prop data [storage:ArrayObject:private] => Array ( [arr] => array data ) )
Anyone could help me understanding what is the difference between using this constant or not?
Thanks in advance!
The ArrayObject and ArrayIterator are 2 classes that are really similar. They actually both share lot of code internally inside the php core. These two classes have a internal array to store the elements you set to those classes.
The STD_PROP_LIST tells us how to read, and ARRAY_AS_PROPS tells us how we to write those elements. First of all,setting elements through the standard array ([]) notation will always work the same way, regardless of these settings.
When setting ARRAY_AS_PROPS flags, it means that when you set properties (through the ->), will not be set on the object like you would expect with regular objects, but will be stored as internal elements. If this flag is NOT set, it will store the property onto the actual array-object or array-iterator, which is what you see in the code output from your example: the "prop => propdata" is not inside the storage:ArrayObject:private, which would have been the case if the ARRAY_AS_PROPS flag would have been set:
$a = new ArrayObject();
$a['arr'] = 'array data';
$a->prop = 'prop data';
$b = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS);
$b['arr'] = 'array data';
$b->prop = 'prop data';
print_r($a);
print_r($b);
// Output:
ArrayObject Object
(
[prop] => prop data
[storage:ArrayObject:private] => Array
(
[arr] => array data
)
)
ArrayObject Object
(
[storage:ArrayObject:private] => Array
(
[arr] => array data
[prop] => prop data
)
)
The STD_PROP_LIST decides on what to return on certain conditions, most notably at var_dump(). Though there will be other cases, i haven't found them myself. If the STD_PROP_LIST is set, it will return the properties that have been set onto your ArrayObject, or ArrayIterator class. If it's NOT set, then var_dump() will return a list of the internal elements that have been stored.
The actual documentation is not 100% correct on STD_PROP_LIST. This flag affects var_dump(), but not foreach(). When using foreach(), it will always iterate the internal elements, and never the actual properties, even when STD_PROP_LIST has been set.
These two flags are not mutually exclusive: you can set both flags, but it wouldn't make much sense doing so: it means that properties are always added as internal elements (ARRAY_AS_PROPS), and we want to return the standard properties through var_dump (STD_PROP_LIST). Since properties cannot have been set, it will always return an empty list in that case.
A great answer by #JayTaph but print_r is more like a debug function. To actually use the arrays in for instance a foreach it becomes clear that the both differ significantly:
$a = new ArrayObject();
$a['arr'] = 'array data';
$a->prop = 'prop data';
$b = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS);
$b['arr'] = 'array data';
$b->prop = 'prop data';
echo "\$a:<br>\n";
foreach( $a as $key=> $value) {
printf( "[%s] : %s<br>\n", $key, $value);
}
echo "\$b:<br>\n";
foreach ($b as $key => $value) {
printf("[%s] : %s<br>\n", $key, $value);
}
will output:
$a:
[arr] : array data
$b:
[arr] : array data
[prop] : prop data
Lets say I have an multidimensional string array:
.food = array(
'vegetable' => array(
'carrot' => 'blablue',
'potato' => 'bluebla',
'cauliflower' => 'blabla'
),
'Fruit' => array(
'apple' => 'chicken65',
'orange' => 'salsafood',
'pear' => 'lokkulakka'
)
);
is it possible to access the array by using index as numbers, instead of using the name of the key?
So for accessing chicken65 , I will type echo $food[1][0]; I don't want to use numbers as key, because its a big array and its more user-friendly if I use string as key and it will let me do for-loops on advanced level.
You can do foreach loops to achieve much the same thing as a typical for-loop.
foreach ($foods as $key => $value) {
//For the first iteration, $key will equal 'vegetable' and $value will be the array
}
$food[1][0] != $food[1]['apple'], so you cannot use numeric keys in this case.
try
$new_array = array_values($food);
however, variable can't start with .. It should start with $
you may want to try the function array_values but since you are dealing with multidemsional arrays, here is a solution posted by a php programmer
http://www.php.net/manual/en/function.array-values.php#103905
but it would be easier to use foreach instead of for.
You can use array_keys() on the array. The resulting array can be traversed via a for-loop and gives you the associative key.
I will show it to you for the first dimension:
$aTest = array('lol' => 'lolval', 'rofl' => 'roflval');
$aKeys = array_keys($aTest);
$iCnt = count($aKeys);
for($i = 0; $i < $iCnt; ++$i)
{
var_dump($aTest[$aKeys[$i]]);
}
You would need to do this for two dimensions but I would not recommend this. It is actually more obstrusive and slower than most other solutions.
I don't think there is something native to go this route.
And it does seem like you are trying to stretch array use a bit.
You should go OOP on this one.
Create a FoodFamilly object and a Food object in which you can store arrays if necessary and you'll be able to write a nice user-friendly code and add indices if needed.
OOP is almost always the answer :)