I have 3 array like
$arr = [
"color" => [["name"=>"red"]],
"size" => [["name"=>"18 inch"], ["name"=>"15 inch"]],
"type" => [["name"=>"plastic"]]
]
$combo = array();
foreach ($arr['size'] as $size) {
foreach($arr['color'] as $color){
foreach ($arr['type'] as $type) {
$variant = json_encode(['size' => $size->name, 'color' =>
$color->name, 'type' => $type->name]);
array_push($combo,$variant);
}
}
}
echo $combo;
// result
0 => "{"size":"15 inch","color":"yellow","type":"metal"}"
1 => "{"size":"18 inch","color":"yellow","type":"plastic"}"
It works properly but but there is can be less or more variants. How can I handle this.
For example
$arr = [
"size" => [["name"=>"18 inch"], ["name"=>"15 inch"]],
"type" => [["name"=>"plastic"]]
]
Or
$arr = [
"color" => [["name"=>"red"]],
"size" => [["name"=>"18 inch"], ["name"=>"15 inch"]],
"type" => [["name"=>"plastic"]],
"brand" => [['name' => 'something']],
]
For what i understand, you have to combine the arrays of properties into one array of
object.
I have to leave now, but if you need a explanation leave a comment and i updated the answers
$arr = [
"color" => [["name"=>"red"],['name'=>'yellow']],
"size" => [["name"=>"18 inch"], ["name"=>"15 inch"]],
"type" => [["name"=>"plastic"]],
"brand" => [['name' => 'something']],
];
function runFor($arr ,&$array, $keys,$index,&$positions){
foreach ($arr[$keys[$index]] as $key => $espec){
$positions[$keys[$index]] = $key;
if($index + 1 < count($keys)){
runFor($arr,$array,$keys, $index+1,$positions);
}else{
$item = (object)[];
foreach ($keys as $key){
$item->$key = $arr[$key][$positions[$key]]['name'];
}
array_push($array,$item);
}
unset($positions[$keys[$index]]);
}
}
$array = array();
$keys = array_keys($arr);
$positions = [];
runFor($arr,$array,$keys,0,$positions);
$combo = array();
foreach ($array as $item){
array_push($combo,json_encode($item));
}
var_dump($combo);
Related
I have an array of this sort:
$array = [
"Darren" => [
"age" => "18",
"work" => [
"occupation" => "developer",
"company" => "ABC Ltd"
]
],
"John" => [
"age" => "24",
"work" => [
"occupation" => "developer",
"company" => "ABC Ltd",
"url" => "www.example.com"
],
]
]
And would like to merge the keys with a dot in between, depending on the array's hierachy:
"Darren.age"
"Darren.work.occupation"
"Darren.work.company"
...
The function that I made so far is
public function buildExpressionKey($array, $parentKey = null){
$expression = [];
foreach($array as $key=>$value){
if(is_array($value)){
array_push($expression, $parentKey. implode(".",
$this->buildExpressionKey($value, $key)));
}else{
array_push($expression, $key);
}
}
return $expression;
}
it is returning this value at the moment:
[
[0] => "age.Darrenoccupation.company"
[1] => "age.Johnoccupation.company.url"
]
Was wondering if it is possible to make a function which automatically does merges the keys like that, thanks in advance :)
What you are currently asking for:
<?php
$people =
[
'John' =>
[
'Occupation' => 'Developer',
'Age' => 18
],
'Darren' =>
[
'Occupation' => 'Manager',
'Age' => 40
]
];
foreach($people as $name => $value)
foreach($value as $k => $v)
$strings[] = $name . '.' . $k;
var_export($strings);
Output:
array (
0 => 'John.Occupation',
1 => 'John.Age',
2 => 'Darren.Occupation',
3 => 'Darren.Age',
)
Managed to resolve this issue :)
/**
* #param $array
* #return array
*/
public function buildExpressionKey($array){
$iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array));
$keys = array();
foreach ($iterator as $key => $value) {
// Build long key name based on parent keys
for ($i = $iterator->getDepth() - 1; $i >= 0; $i--) {
$key = $iterator->getSubIterator($i)->key() . '.' . $key;
}
$keys[] = $key;
}
return $keys;
}
Found something similar on here: Get array's key recursively and create underscore separated string
I have such array:
array:8 [
"text" => "rt_field"
"title" => "rt_field"
"type_id" => "rt_attr_uint"
"author_id" => "rt_attr_uint"
"created_at" => "rt_attr_timestamp"
"recommended_at" => "rt_attr_timestamp"
"deleted_at" => "rt_attr_timestamp"
"feeds" => "rt_attr_multi"
]
I need to get this:
array:10 [
"text" => "rt_attr_string"
"text_txt" => "rt_field"
"title" => "rt_attr_string"
"title_txt" => "rt_field"
"type_id" => "rt_attr_uint"
"author_id" => "rt_attr_uint"
"created_at" => "rt_attr_timestamp"
"recommended_at" => "rt_attr_timestamp"
"deleted_at" => "rt_attr_timestamp"
"feeds" => "rt_attr_multi"
]
I try parse array ($key => $value). When $value == rt_field: I try rename $key to $key.'_txt', and add such key as default (without _txt) with $value = rt_attr_string.
My code:
foreach ($array_param as $key => $value) {
if ($value == 'rt_field'){
$array_param_second[$key] = 'rt_attr_string';
$array_param[$key] = $key.'_txt';
}
}
$result = array_merge($array_param, $array_param_second);
return $result;
But $key in first array doesn't edit.
What I do wrong?
You are editing the value in either array. If you want to update a key, you need to create a new key.
You can just add the keys to a new array, this way there is no need for merging after the foreach.
$result = [];
foreach ($array_param as $key => $value) {
if ($value == 'rt_field'){
$result[$key] = 'rt_attr_string';
$result[$key . '_txt'] = $value;
} else {
$result[$key] = $value;
}
}
Here is your solution....
Your Array
$array[] = array(
"text" => "rt_field",
"title" => "rt_field",
"type_id" => "rt_attr_uint",
"author_id" => "rt_attr_uint",
"created_at" => "rt_attr_timestamp",
"recommended_at" => "rt_attr_timestamp",
"deleted_at" => "rt_attr_timestamp",
"feeds" => "rt_attr_multi"
);
Solution
$new = array();
$keys = array_keys($array[0]);
foreach($array as $r){
for($i=0;$i<count($keys);$i++){
$key = $keys[$i];
if($r[$key]=='rt_field'){
$new[$key.'_txt'] = $r[$key];
$new[$key] = 'rt_attr_string';
}
else $new[$i][$key] = $r[$key];
}
}
echo "<pre>";print_r($new);
I am trying to turn a string into a nested array
Here is my string:
a/b/d.docx
and I wanted to be like this:
array(
"name" => "a",
"type" => "folder",
"sub" => array(
"name" => "b",
"type" => "folder",
"sub" => array(
"name" => "c.docx",
"type" => "file",
"size" => "20"
)
)
)
This is the code that I have so far
$items = explode('/', $strings);
$num = count($items);
$num = --$num;
$temp = array();
foreach($items as $keys => $value) {
$temp[$keys] = array(
"name" => $value,
"type" => "folder",
"items" => $temp[++$keys]
);
if($keys == $num){
$temp[$keys] = array(
"name" => $value,
"type" => "file",
"size" => "20"
);
}
}
var_dump($temp);
I am trying this functions but this only turn string into a single array and it also can't do the 'items' line.
Any help would be appreciated.Thanks.
Note that the path is virtual and doesn't exist.
UPDATE: How can I add path to each array??for example,"path"=>"a/b"
You can do that:
$path = 'a/b/d.docx';
$parts = explode('/', $path);
$result = [ 'name' => array_pop($parts), 'type' => 'file', 'size' => 20 ];
while ($parts) {
$result = [ 'name' => array_pop($parts), 'type' => 'folder', 'sub' => $result ];
}
print_r($result);
<?php
$strings='a/b/d.docx';
$items = explode('/', $strings);
$num = count($items)-1;
$root= array();
$cur = &$root;
$v='';
foreach($items as $keys => $value) {
$v = $v.$value;
$temp = array( "name" => $value, "path"=>$v, "type" => "folder", "items" => "");
if($keys == $num){
$temp = array( "name" => $value, "path"=>$v, "type" => "file", "size" => "20");
}
$v= $v.'/';
if($keys==0) {
$cur = $temp;
}
else
{
$cur['items'] = $temp;
$cur = &$cur['items'];
}
}
var_dump($root);
Try recursion:
public function testAction(){
$sString = 'a/b/c/d.exe';
$aExploded = explode('/', $sString);
var_dump($this->_parse_folder_rec($aExploded));
}
private function _parse_folder_rec($aExploded){
$aResult = [];
$aResult['name'] = array_shift($aExploded);
if($aExploded){
$aResult['type'] = 'folder';
$aResult['sub'] = $this->_parse_folder_rec($aExploded);
}else{
$aResult['type'] = 'file';
$aResult['size'] = 20;
}
return $aResult;
}
The question is simple, I want to create the array below dynamically, but the code I got now only outputs the last row. Is there anybody who knows what is wrong with my dynamically array creation?
$workingArray = [];
$workingArray =
[
0 =>
[
'id' => 1,
'name' => 'Name1',
],
1 =>
[
'id' => 2,
'name' => 'Name2',
]
];
echo json_encode($workingArray);
/* My not working array */
$i = 0;
$code = $_POST['code'];
$dynamicArray = [];
foreach ($Optionsclass->get_options() as $key => $value)
{
if ($value['id'] == $code)
{
$dynamicArray =
[
$i =>
[
'id' => $key,
'name' => $value['options']
]
];
$i++;
}
}
echo json_encode($dynamicArray);
You dont need to have the $i stuff that is adding another level to your array that you dont want.
$code = $_POST['code'];
$dynamicArray = [];
foreach ($Optionsclass->get_options() as $key => $value)
{
if ($value['id'] == $code)
{
$dynamicArray[] = ['id' => $key, 'name' => $value['options'];
}
}
echo json_encode($dynamicArray);
You are creating a new dynamic array at each iteration:
$dynamicArray =
[
$i =>
[
'id' => $key,
'name' => $value['options']
]
];
Instead, declare $dynamicArray = []; above the foreach, and then use:
array_push($dynamicArray, [ 'id' => $key, 'name' => $value['options']);
inside the array.
I have two arrays that look like this:
(this one is ordered by value_max)
$max_values = [
["name" => "john", "id" => 5, "value_max" => 500],
["name" => "john", "id" => 3, "value_max" => 200],
...
];
$min_values = [
["name" => "john", "id" => 5, "value_min" => 100],
["name" => "john", "id" => 3, "value_min" => 150],
...
];
And I need to have a final array like this:
(This one stills need to be ordered by value_max, so I assume I could just overwrite the first array with the calculations done with the second)
$max_and_difference_values = [
["name" => "john", "id" => 5, "value_max" => 500, "difference_value" => 400],
["name" => "john", "id" => 3, "value_max" => 200, "difference_value" => 50 ],
...
];
My question is pretty straight: What is the best/effective way to run through both first arrays and build the last one. Assuming that the size of the arrays can be of around 150 elements.
To avoid looping through all arrays repeatedly, index one array by the field you want to merge on, i.e. the 'id' key:
$second = array_combine(array_map(function ($i) { return $i['id']; }, $second_array), $second_array);
Then looping through the other and comparing the values is pretty easy:
$third = array();
foreach ($first_array as $i) {
$third[] = $i + array('difference_value' => $i['value_max'] - $second[$i['id']]['value_min']);
}
If it's guaranteed that both arrays will have exactly matching keys, you don't even need the first step and just go by already existing keys.
This will sort your array. So you can sort the second array.
<?php
$min_values = array(
array("name" => "john", "id" => 5, "value_min" => 100),
array("name" => "john", "id" => 3, "value_min" => 150),
);
function aasort (&$array, $key) {
$sorter=array();
$ret=array();
reset($array);
foreach ($array as $ii => $va) {
$sorter[$ii]=$va[$key];
}
asort($sorter);
foreach ($sorter as $ii => $va) {
$ret[$ii]=$array[$ii];
}
$array=$ret;
}
aasort($min_values,"id");
echo "<pre>";
print_r($min_values);
echo "</pre>";
?>
And then you can use the logic what Alessandro Minoccheri mentioned.
$arr = array();
for ($i=0; $i<count($first_array);$i++){
$arr['name'] = $first_array[$i]['name'];
$arr['id'] = $first_array[$i]['id'];
$arr['value_max'] = $first_array[$i]['value_max'];
$arr['difference_value'] = $first_array[$i]['value_max']-$second[$i['id']]['value_max'] ;
}
As you have not shared how the second array with the minimum values is ordered (in itself and relative to the maximum values array), I'd say, index the minimum values by the id entry and then do the calculation in a second iteration. It should be fast enough, 150 elements is just "nothing":
$max_values = [
["name" => "john", "id" => 5, "value_max" => 500],
["name" => "john", "id" => 3, "value_max" => 200],
];
$min_values = [
["name" => "john", "id" => 5, "value_min" => 100],
["name" => "john", "id" => 3, "value_min" => 150],
];
$min_values_by_id = [];
foreach($min_values as $min) {
$min_values_by_id[$min['id']] = $min['value_min'];
}
$max_and_difference_values = $max_values;
foreach($max_and_difference_values as &$entry)
{
$entry['difference_value'] = $entry['value_max'] - $min_values_by_id[$entry['id']];
}
unset($entry);
print_r($max_and_difference_values);
This is just a straight forward example, nothing fancy. Demo
the following works for me. I'm not a PHP expert though, i.e. I'm not so familiar with cloning (note the empty clone array). Note that it only copies existing properties (if one array does contain a min_value and another does only contain a some other key)
In essence
function convertArr( $arr ) {
// Easy referencing without having to search through the arrays more than once for a matching id
$new_arr = array();
foreach( $arr as $array ) {
$new_arr[ $array['id'] ] = cloneArr( $array );
}
return $new_arr;
}
function merge( $arr1, $arr2 ) {
$convertedArr1 = convertArr( $arr1 );
$convertedArr2 = convertArr( $arr2 );
$arr = array();
// Based on the ordered array
foreach( $convertedArr1 as $array ) {
$id = $array['id'];
$tempArr = array();
foreach( $convertedArr1[ $id ] as $k => $v ) {
$tempArr[ $k ] = $v;
}
foreach( $convertedArr2[ $id ] as $k => $v ) {
$tempArr[ $k ] = $v;
}
array_push( $arr, $tempArr );
}
return $arr;
}
Full example:
<?php
//$arr1 = [ ["name" => "john", "id" => 5, "value_max" => 500], ["name" => "john", "id" => 3, "value_max" => 200] ];
//$arr2 = [ ["name" => "john", "id" => 5, "value_min" => 100], ["name" => "john", "id" => 3, "value_min" => 150] ];
$arr1 = array(
array( "name" => "john", "id" => 5, "value_max" => 500 ),
array( "name" => "john", "id" => 3, "value_max" => 200 )
);
$arr2 = array(
array( "name" => "john", "id" => 5, "value_min" => 100 ),
array( "name" => "john", "id" => 3, "value_min" => 150 )
);
function neatPrint( $arr ) {
echo "<pre>";
print_r( $arr );
echo "</pre>";
}
echo "<h2>Before</h2>";
neatPrint( $arr1 );
neatPrint( $arr2 );
echo "<hr/>";
function cloneArr( $old ) {
// I dunno how to properly clone
return $old;
}
function convertArr( $arr ) {
// Easy referencing without having to search through the arrays more than once for a matching id
$new_arr = array();
foreach( $arr as $array ) {
$new_arr[ $array['id'] ] = cloneArr( $array );
}
return $new_arr;
}
function merge( $arr1, $arr2 ) {
$convertedArr1 = convertArr( $arr1 );
$convertedArr2 = convertArr( $arr2 );
$arr = array();
// Based on the ordered array
foreach( $convertedArr1 as $array ) {
$id = $array['id'];
$tempArr = array();
neatPrint( $convertedArr1[ $id ] );
neatPrint( $convertedArr2[ $id ] );
foreach( $convertedArr1[ $id ] as $k => $v ) {
$tempArr[ $k ] = $v;
}
foreach( $convertedArr2[ $id ] as $k => $v ) {
$tempArr[ $k ] = $v;
}
array_push( $arr, $tempArr );
}
echo "<h2>Result</h2>";
return $arr;
}
echo "<h2>Loopthrough</h2>";
neatPrint( merge( $arr1, $arr2 ) );
?>
Let me know what you think :-)
if the element are in order try this code:
$arr = array();
for ($i=0; $i<count($first_array);$i++){
$arr['name'] = $first_array[$i]['name'];
$arr['id'] = $first_array[$i]['id'];
$arr['value_max'] = $first_array[$i]['value_max'];
$arr['difference_value'] = $first_array[$i]['value_max']-$second[$i['id']]['value_max'] ;
}