I have an array mind
[{"id":"331","file_name":"3b1379e2496408dd4c865f5f63f96bf6","file_path":"https://path/3b1379e2496408dd4c865f5f63f96bf6.png"},
{"id":"332","file_name":"d0ef559473a061086592bceed0880a01","file_path":"https://path/d0ef559473a061086592bceed0880a01.png"}]
I need to output this array so that in the end it looks like this
[{url:"https://path/3b1379e2496408dd4c865f5f63f96bf6.png"},
{url:"https://path/d0ef559473a061086592bceed0880a01.png"}]
To output only one field from an array, I use
array_column($array, 'file_path')
And I end up with
["https://path/3b1379e2496408dd4c865f5f63f96bf6.png",
"https://path/d0ef559473a061086592bceed0880a01.png"]
But how now to make these fields be objects and add a url in front of them?
You can use a mapping operation:
array_map(
fn($value) => (object) ['url' => $value],
array_column($array, 'file_path')
)
https://3v4l.org/vbguH
For 7.3 and below (no arrow function support):
array_map(
function($value) {
return (object) ['url' => $value];
},
array_column($array, 'file_path')
)
Note, unless you want object syntax or features in PHP ($foo->url), you can omit the (object) casting; it will still JSON encode with object syntax unless you tell it not to.
Here's a dirt-basic version - simply loop through the array and make a new one with just the property you want in each entry:
$json = '[{"id":"331","file_name":"3b1379e2496408dd4c865f5f63f96bf6","file_path":"https://path/3b1379e2496408dd4c865f5f63f96bf6.png"},
{"id":"332","file_name":"d0ef559473a061086592bceed0880a01","file_path":"https://path/d0ef559473a061086592bceed0880a01.png"}]';
$arr = json_decode($json, true);
$output = [];
foreach ($arr as $item)
{
$output[] = ["url" => $item["file_path"]];
}
echo json_encode($output);
Demo: https://3v4l.org/JcKZE
Or for a slick one-liner, make use of the array_map function:
In the above, replace the $output = []; and the foreach loop with:
$output = array_map(fn($value) => (object) ['url' => $value], array_column($arr, 'file_path'));
Demo: https://3v4l.org/a10kB
Related
I am trying to convert a data source (Array ( [0] => [1] => [2] => 1 [3] =>...) to use in json. In my php page, I use json_encode((object) $data) (also works as json_encode($data, JSON_FORCE_OBJECT)) which yields an array that looks like: {"0":false,"1":false,"2":true,"3":false,...}. I would like to add a character in front of the key, returning as {"A0":false,"A1":false,"A2":true,"A3":false,...}. How do I go about doing so?
I have searched this forum and google extensively but am having no luck. How do I prepend or concatenate a character to the key?
If you are working in PHP, then I would suggest to do any manipulation in PHP before json_encodeing.
Say your array is called $arr:
//Make array of new keys
$newKeys = array_map(function($k){return 'A'.$k;}, array_keys($arr));
//Combine new keys with value
$newArray = array_combine($newKeys, $arr);
This should work:
<?php
$source = [0 => 'bla', 1 => 'blop'];
// Get your keys
$keys = array_keys($source);
// Prepend whatever to each key
$formatted_keys = array_map(function ($key) {
return 'A' . $key;
}, $keys);
// Build a new array using $formatted_keys for keys
// and array_values($source) for values.
$result = array_combine($formatted_keys, array_values($source));
http://php.net/manual/en/function.array-keys.php
http://php.net/manual/en/function.array-values.php
http://php.net/manual/en/function.array-combine.php
You could replace the array keys like this:
foreach ($data as $key=>$value)
{
$data["A".$key] = $value;
unset($data[$key]);
}
Suppose I have this array,
$cast = [
'jon' => [
'fullname' => 'Jon Snow',
'class' => 'warrior',
],
'margery' => [
'fullname' => 'Margery Tyell',
'class' => 'politician'
]
];
How do I get the key and it's certain value only? like this,
$name = ['jon'=>'Jon Snow', 'margery'=>'Margery Tyrell'];
Is there any function that support this, so It doesn't have to be loop ?
Any answer will be appreciated!
You can iterate through the multidimensional array, and add the key and the value at index fullname of the inner array in a new one-dimensional array like this:
$names = [];
foreach ($cast as $character => $character_details) {
$names[$character] = $character_details['fullname'];
}
EDIT Alternatively, if you don't want to loop through the elements, you could use array_map function which takes a function as an argument where you can specify how to map each element of the array. In your case, you would simply return the fullname of an element.
$names = array_map(
function ($value) {
return $value['fullname'];
},
$cast
);
I guess that you have iterate over it and extract only interesting you keys. Here you have an example:
function getValuesForKey($array, $key){
$result = [];
foreach($array as $k => $subarray){
if(isset($subarray[$key])){
$result[$k] = $subarray[$key];
}
}
return $result;
}
Let's pretend I have this:
$str = "/a/b/c/d/";
$arr = array_filter( explode("/", $str );
At this point $arr contains 4 elements. Is there a way I could create a path in an array with those 4 elements, such as:
$result = [
"a" => [
"b" => [
"c" => [
"d" => [
]
]
]
]
]
...without iterating over $arr?
I know that
$x["a"]["b"]["c"]["d"] = 1;
is perfectly valid and it will create a 4 levels array even if $x wasn't declared as an array, so what I'm asking should be possible.
I DO NOT recommend this as there are security implications when using eval(). However, because I stated in the comments that it couldn't be done without iteration, I felt compelled to post this as an answer (yes, I know implode() iterates internally).
$str = "/a/b/c/d/";
$arr = array_filter( explode("/", $str ));
$keys = '["'.implode('"]["', $arr).'"]';
eval('$x'.$keys.' = 1;');
print_r($x);
For a more practical way see How to write getter/setter to access multi-leveled array by dot separated key names?
I wrote a function once, that had this behaviour as a side effect. It doesn't iterate, but uses recursion.
See: https://github.com/feeela/php-utils/blob/master/function.getArrayValueReference.php
You may call like that:
<?php
$newArray = array();
$keys = 'a/b/c/d';
$referenceToD =& getArrayValueReference( $newArray, explode( '/', $keys ), true );
$referenceToD[0] = 'foo';
$referenceToD[1] = 'bar';
print_r( $newArray );
This modifies the array $newArray and creates all the levels. The functions return value is a reference to the last key ('d' in that example).
…which results in:
Array (
[a] => Array (
[b] => Array (
[c] => Array (
[d] => Array (
[0] => foo
[1] => bar
)
)
)
)
)
There is no way to use all the values of $arr without iterating over it.
I guess you don't want to write a foreach loop but use some PHP function that does the iteration for you.
A simple solution that iterates two times over the array (behind the scene)
This is a possible solution:
$x = array_reduce(
array_reverse($arr),
function ($carry, $item) {
return [$item => $carry];
},
1
);
It generates the same result as:
$x = [];
$x['a']['b']['c']['d'] = 1;
Unfortunately it iterates over $arr two times (array_reverse() and array_reduce()).
Another solution that generates a hierarchy of objects
Another approach that generates the required embedding using objects (stdClass) instead of arrays:
$out = new stdClass;
array_reduce(
$arr,
function ($carry, $item) {
$v = new stdClass;
$carry->{$item} = $v;
return $v;
},
$out
);
It works using a single iteration over $arr but it relies on the way the objects are handled in PHP to work (and this doesn't work with arrays).
PHP handles the objects in a way that makes them look like they are passed by reference. It's a common misconception that the objects are "passed by reference" in PHP but this is not true. A double indirection is responsible for this behaviour.
A recursive solution
function makeArray(array $arr, $initial)
{
if (! count($arr)) {
return $initial;
} else {
$key = array_shift($arr);
return [ $key => makeArray($arr, $initial) ];
}
}
$out = makeArray($arr, 1);
This solution iterates only once over the array and generates a hierarchy of arrays but recursivity is disastrous for large input arrays because it uses a lot of memory.
I have this php associative array.
array(
'Location_1' => 'Link_1',
'Location_2' => 'Link_2'
)
I would like to convert it into a json output using json_encode() that looks like this;
[{"Location_name":"Location_1","Link_name":"Link_1"},{"Location_name":"Location_2","Link_name":"Link_2"}]
How can this be done? The challenging part to me seems like how to add the Location_name and Link_name in front. Thank you very much.
<?php
// original array
$a = array(
'Location_1' => 'Link_1',
'Location_2' => 'Link_2'
);
// transform
$b = array();
foreach($a as $key=>$value) {
$b[] = array('Location_name'=>$key, 'Link_name'=>$value);
}
// output
echo json_encode($b);
?>
Result:
[{"Location_name":"Location_1","Link_name":"Link_1"},{"Location_name":"Location_2","Link_name":"Link_2"}]
You Can use StdClass anonymous Objects.
<?php
$newArray = array();
$array = array(
'Location_1' => 'Link_1',
'Location_2' => 'Link_2'
);
foreach ($array as $key => $value) {
$object = new StdClass();
$object->Location_name = $key;
$object->Link_name = $value;
$newArray[] = $object;
}
var_dump(json_encode($newArray));
So first things first:
convert it into a json output using json_encode() that looks like this
This is not possible. json_encode just encodes arrays to JSON, you need to do the formatting work yourself.
And on that note
array_map should do the trick.
Try this:
$arr = array(
'Location_1' => 'Link_1',
'Location_2' => 'Link_2'
);
$output = array_map(
function( $key, $val ){
return array(
"Location_name" => $key,
"Link_name" => $val
);
}, array_keys( $arr ), $arr );
echo json_encode( $output );
I have an array $data
fruit => apple,
seat => sofa,
etc. I want to loop through so that each key becomes type_key[0]['value'] so eg
type_fruit[0]['value'] => apple,
type_seat[0]['value'] => sofa,
and what I thought would do this, namely
foreach ($data as $key => $value)
{
# Create a new, renamed, key.
$array[str_replace("/(.+)/", "type_$1[0]['value']", $key)] = $value;
# Destroy the old key/value pair
unset($array[$key]);
}
print_r($array);
Doesn't work. How can I make it work?
Also, I want everything to be in the keys (not the values) to be lowercase: is there an easy way of doing this too? Thanks.
Do you mean you want to make the keys into separate arrays? Or did you mean to just change the keys in the same array?
$array = array();
foreach ($data as $key => $value)
{
$array['type_' . strtolower($key)] = array(array('value' => $value));
}
if you want your keys to be separate variables, then do this:
extract($array);
Now you will have $type_fruit and $type_sofa. You can find your values as $type_fruit[0]['value'], since we put an extra nested array in there.
Your requirements sound... suspect. Perhaps you meant something like the following:
$arr = array('fruit' => 'apple', 'seat' => 'sofa');
$newarr = array();
foreach ($arr as $key => $value)
{
$newkey = strtolower("type_$key");
$newarr[$newkey] = array(array('value' => $value));
}
var_dump($newarr);
First I wouldn't alter the input-array but create a new one unless you're in serious, serious trouble with your memory limit.
And then you can't simply replace the key to add a deeper nested level to an array.
$x[ 'abc[def]' ] is still only referencing a top-level element, since abc[def] is parsed as one string, but you want $x['abc']['def'].
$data = array(
'fruit' => 'apple',
'seat' => 'sofa'
);
$result = array();
foreach($data as $key=>$value) {
$target = 'type_'.$key;
// this might be superfluous, but who knows... if you want to process more than one array this might be an issue.
if ( !isset($result[$target]) || !is_array($result[$target]) ) {
$result[$target] = array();
}
$result[$target][] = array('value'=>$value);
}
var_dump($result);
for starters
$array[str_replace("/(.+)/", "type_$1[0]['value']", $key)] = $value;
should be
$array[str_replace("/(.+)/", type_$1[0]['value'], $key)] = $value;