Related
I need to group values in my flat array so that each non-integer value starts a new group/row in my result array and every integer value encountered until the next occurring non-integer should be pushed into a subarray in the respective group/row.
Input:
$unitsList = [
"Aulas Gratuitas",
"149",
"151",
"153",
"Módulo 0",
"964",
"989",
"Módulo 1",
"985",
"1079",
"1001",
"1003"
"Módulo 2",
"1009"
];
Current code:
$newArr = array();
foreach( $unitsList as $item ) {
if( !is_numeric($item) ) {
$title = array( "title" => $item, "units" => "" );
array_push( $newArr, $title);
} elseif ( is_numeric($item) ) {
$number = $item;
array_push( $newArr, $number);
}
}
Current result:
[
[
"title" => "Aulas Gratuitas",
"units" => ""
]
"149",
"151",
"153",
[
"title" => "Módulo 0",
"units" => ""
],
"964",
"989",
[
"title" => 'Módulo 1',
"units" => ""
],
"985",
"1079",
"1001",
"1003"
[
"title" => 'Módulo 2',
"units" => ''
],
"1009"
]
As you can see, I am having a hard time adding the numbers into the "units" key.
Desired result:
[
[
"title" => "Aulas Gratuitas",
"units" => ["149", "151", "153"]
],
[
"title" => 'Módulo 0',
"units" => ["964", "989"]
],
[
"title" => 'Módulo 1',
"units" => ["985", "1079", "1001", "1003"]
],
[
"title" => "Módulo 2",
"units" => ["1009"]
]
]
So that you don't need to keep track of first level indexes, use a reference variable and push related data into that AFTER pushing the new row into the result array.
Code: (Demo)
$result = [];
foreach ($array as $value) {
if (!ctype_digit($value)) {
unset($units);
$units = [];
$result[] = ['title' => $value, 'units' => &$units];
} else {
$units[] = $value;
}
}
var_export($result);
unset() is used to destroy the reference to the previous group, otherwise newly pushed data would be sent to two (or more) places in the result array.
Reference variables have a default value of null. If your title values are guaranteed to be followed by an integer/unit value, then $units = []; can be removed. If you have a title and then another title there will be no data for the former title group. With the explicit array declaration, the group will have an empty units array instead of null.
Related questions answered with the same general technique:
Group array of objects into deeper parent-child structure
Split flat array into grouped subarrays containing values from consecutive key in the input array
How to split a string by repeated characters in PHP?
If you are running PHP7.3 or higher (and by this point you definitely should be) AND you are intimidated/mystified by using a reference variable, then you can leverage array_key_last() to locate the latest created array row.
Code: (Demo)
$result = [];
foreach ($array as $value) {
if (!ctype_digit($value)) {
$result[] = ['title' => $value, 'units' => []];
} else {
$result[array_key_last($result)]['units'][] = $value;
}
}
var_export($result);
Items in the given list aren't regular. The first item has three units, and the second has two units. We cannot convert them into the expected structure without controlling the type of each item. My solution is below. I added explanations as a comment line.
$values = array(
"string",
11111,
22222,
33333,
"string_2",
44444,
55555
);
$formattedArray = [];
$index = -1;
foreach ($values as $value) {
// If the value is a string, create the new array structure item and assign the title
if (is_string($value)) {
$index++;
$formattedArray[$index]['title'] = $value;
$formattedArray[$index]['units'] = [];
// The rest of the code in "foreach scope" is for integer values, so skip the remaining part
continue;
}
// If the following line is executing, the value is an integer
// Push the value to the current item's units
$formattedArray[$index]['units'][] = $value;
}
var_dump($formattedArray);
$originalArray = ['a', 1, 2, 3, 'b', 4, 5, 6];
function formatArray($input) {
$output = [];
foreach($input as $inputRow) {
if (is_string($inputRow)) {
$output[] = ['title' => $inputRow, 'units' => []];
} elseif (count($output)) {
$output[count($output)-1]['units'][] = $inputRow;
}
}
return $output;
}
var_dump(formatArray($originalArray));
Note that your numbers after the title CANNOT be strings, otherwise this function will recognize it as new titles.
This code will output:
array(2) {
[0]=>
array(2) {
["title"]=>
string(1) "a"
["units"]=>
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
}
[1]=>
array(2) {
["title"]=>
string(1) "b"
["units"]=>
array(3) {
[0]=>
int(4)
[1]=>
int(5)
[2]=>
int(6)
}
}
}
Approach: loop over values in array, check for value if its converted to int is equal to 0, So group by that key, otherwise accumelate they next elements.
<?php
$unitsList = [ "Aulas Gratuitas", "149", "151", "153", "Módulo 0", "964", "989", "Módulo 1", "985", "1079", "1001", "1003", "Módulo 2", "1009" ];
$result = [];
foreach ($unitsList as $key => $value) {
if(intval($value)==0){
$result[] = ['title' => $value, 'units' => []];
}else{
$result[count($result)-1]['units'][] = $value;
}
}
print_r(array_values($result));
?>
I have a json array like below. I need to get the index into a new array, how is this possible? Arrays are my weakness for some reason just cant grasp them. I can easily get id value, but cannot get the index (e.g 11111111). Any help would be appreciated.
Update please see the revised, my fault for not including the full multi dimensional array.
Below only outputs one result where I need all results.
<?php
$json = '[{
"11111111": {
"id": "val_somevalue5555",
"customer": {
"32312": {
"name": "jane doe"
}
}
},
"2222222": {
"id": "val_somevalue25",
"customer": {
"32312234": {
"name": "jane doe"
}
}
}
}]';
$jsonarr = json_decode($json, true);
$newarr = [];
foreach($jsonarr as $value)
{
$key = key($value);
$newarr[] = ['key' => $key, 'id' => $value[$key]['id']];
}
var_dump($newarr);
expected looped output
key 11111111
id val_somevalue5555
... looped.
You can create an array of the keys of an existing array using the array_keys() function
http://php.net/manual/en/function.array-keys.php
If you don't want the keys in a separate array, and instead just want to access them directly, when you are doing a 'foreach' loop of an array, you can choose to assign a variable to the current key by doing
foreach($jsonarr as $key => $value){...}
Because your original array is actually multidimensional (each $key has a $value that is also stored as an array of "id": "value") - this means taking one more step to get the value of key 'id':
foreach($jsonarr as $key => $value){
$newarray[] = ['key' => $key, 'id' => $value['id'];
}
you can use array_keys() or key() with a foreach loop for this(DEMO):
$newarr = [];
foreach($jsonarr as $value)
{
//$key = array_keys($value)[0];
$key = key($value);
$newarr[] = ['key' => $key, 'id' => $value[$key]['id']];
}
var_dump($newarr);
Output:
array(2) {
[0]=>
array(2) {
["key"]=>
int(11111111)
["id"]=>
string(17) "val_somevalue5555"
}
[1]=>
array(2) {
["key"]=>
int(2222222)
["id"]=>
string(15) "val_somevalue25"
}
}
Edit: With the updated json, you can use the following way, using 2 foreach loops (DEMO):
$newarr = [];
foreach($jsonarr as $json)
{
foreach($json as $key => $value)
{
$newarr[] = ['key' => $key, 'id' => $value['id']];
}
}
PHP supports a slightly different foreach syntax that extracts both the array key and the array value:
foreach ( $jsonarr as $key => $value ) {
$newarr[] = ['key' => $key, 'id' => $value];
}
Use this if you need the key ("11111111" and "2222222" in your example).
<?php
$json = '[{
"11111111": {
"id": "val_somevalue5555"
}
},
{
"2222222": {
"id": "val_somevalue25"
}
}
]';
$jsonarr = json_decode($json, true);
$newarr = [];
foreach($jsonarr as $key => $value) {
$newarr[] = ['key' => key($value), 'id' => current($value)['id']];
}
foreach($newarr as $key) {
echo 'key '.$key['key'] . PHP_EOL;
echo 'id '.$key['id'] . PHP_EOL;
}
If you remove what looks like embedded components in the $json string (otherwise it won't parse) then var_export the output of json_decode() you'll get this:
array (
0 => array (
11111111 => array (
'id' => 'val_somevalue5555',
),
),
1 => array (
2222222 => array (
'id' => 'val_somevalue25',
),
),
)
You have a double-nested array, hence...
foreach ($jsonarr as $obj) {
foreach ($obj as $name=>$value) {
print "$name = $value[id]\n";
break;
}
}
or you can reference the elements directly:
print $jsonarr[0]['11111111']['id'];
First, you are not accessing the deep enough before iterating.
If you call var_export($jsonarr); you will see:
array ( // an indexed array of subarrays
0 =>
array ( // an associative array of subarrays, access via [0] syntax (or a foreach loop that only iterates once)
11111111 => // this is the subarray's key that you want
array (
'id' => 'val_somevalue5555', // this is the value you seek from the id element of 1111111's subarray
'customer' =>
array (
32312 =>
array (
'name' => 'jane doe',
),
),
),
2222222 => // this is the subarray's key that you want
array (
'id' => 'val_somevalue25', // this is the value you seek from the id element of 2222222's subarray
'customer' =>
array (
32312234 =>
array (
'name' => 'jane doe',
),
),
),
),
)
Code: (Demo)
$jsonarr = json_decode($json, true);
$result=[];
// vvvv-avoid a function call (key()) on each iteration by declaring here
foreach($jsonarr[0] as $key=>$subarray){
// ^^^-drill down into the first level (use another foreach loop if there may be more than one)
$result[]=['key'=>$key,'id'=>$subarray['id']];
}
var_export($result);
Output:
array (
0 =>
array (
'key' => 11111111,
'id' => 'val_somevalue5555',
),
1 =>
array (
'key' => 2222222,
'id' => 'val_somevalue25',
),
)
p.s. If $jsonarr has more than one element in its first level, you should use a foreach() loop like this:
foreach($jsonarr as $array1){
foreach($array1 as $key=>$array2){
$result[]=['key'=>$key,'id'=>$array2['id']];
}
}
I am looking to group an array into subarrays based on its keys.
Sample Array
Array
(
[0] => Array
(
[a_id] => 1
[a_name] => A1
[b_id] => 1
[b_name] => B1
[c_id] => 1
[c_name] => C1
)
[1] => Array
(
[a_id] => 1
[a_name] => A1
[b_id] => 1
[b_name] => B1
[c_id] => 2
[c_name] => C2
)
[2] => Array
(
[a_id] => 1
[a_name] => A1
[b_id] => 2
[b_name] => B2
[c_id] => 3
[c_name] => C3
)
[3] => Array
(
[a_id] => 2
[a_name] => A2
[b_id] => 3
[b_name] => B3
[c_id] => 4
[c_name] => C4
)
)
I need this sample array to be converted into a JSON array of the following format:
Expected Output
[{
"a_id": 1,
"a_name": "A1",
"b_list": [{
"b_id": 1,
"b_name": "B1",
"c_list": [{
"c_id": 1,
"c_name": "C1"
}, {
"c_id": 2,
"c_name": "C2"
}]
}, {
"b_id": 2,
"b_name": "B2",
"c_list": [{
"c_id": 3,
"c_name": "C3"
}]
}]
}, {
"a_id": 2,
"a_name": "A2",
"b_list": [{
"b_id": 3,
"b_name": "B3",
"c_list": [{
"c_id": 4,
"c_name": "C4"
}]
}]
}]
I was able to group by a key using the code below.
$array = array(
array("a_id" => "1","a_name" => "A1","b_id" => "1","b_name" => "B1","c_id" => "1","c_name" => "C1"),
array("a_id" => "1","a_name" => "A1","b_id" => "1","b_name" => "B1","c_id" => "2","c_name" => "C2"),
array("a_id" => "1","a_name" => "A1","b_id" => "2","b_name" => "B2","c_id" => "3","c_name" => "C3"),
array("a_id" => "2","a_name" => "A2","b_id" => "3","b_name" => "B3","c_id" => "4","c_name" => "C4")
);
$return = array();
foreach($array as $val) {
$return[$val["a_id"]][] = $val;
}
print_r($return);
But my actual scenario involves grouping into sub arrays didn't worked.
Looking forward to see if there is an optimized way or useful function to get into my expected JSON response.
Note: I am looking into a generalized use case here . For example : a_list as countries,b_list as states and c_list as cities.
Man that is very specific use case for arrays. Well here is your solution.
$array = <YOUR SAMPLE ARRAY>
$output = [];
/*
* Nesting array based on a_id, b_id
*/
foreach ($array as $item) {
$aid = $item['a_id'];
$bid = $item['b_id'];
$cid = $item['c_id'];
if(!isset($output[$aid])){
$output[$aid] = [
'a_id' => $item['a_id'],
'a_name' => $item['a_name'],
'b_list' => [
$bid => [
'b_id' => $item['b_id'],
'b_name' => $item['b_name'],
'c_list' => [
$cid = [
'c_id' => $item['c_id'],
'c_name' => $item['c_name']
]
]
]
]
];
} else if (!isset($output[$aid]['b_list'][$bid])){
$output[$aid]['b_list'][$bid] = [
'b_id' => $item['b_id'],
'b_name' => $item['b_name'],
'c_list' => [
$cid => [
'c_id' => $item['c_id'],
'c_name' => $item['c_name']
]
]
];
} else if(!isset($output[$aid]['b_list'][$bid]['c_list'][$cid])) {
$output[$aid]['b_list'][$bid]['c_list'][$cid] = [
'c_id' => $item['c_id'],
'c_name' => $item['c_name']
];
} else {
// Do/Dont overrider
}
}
/*
* Removing the associativity from the b_list and c_list
*/
function indexed($input){
$output = [];
foreach ($input as $key => $item) {
if(is_array($item)){
if($key == 'b_list' || $key == 'c_list'){
$output[$key] = indexed($item);
} else {
$output[] = indexed($item);
}
} else {
$output[$key] = $item;
}
}
return $output;
}
$indexed = indexed($output);
print_r(json_encode($indexed, 128));
Interesting requirement there.
Here is my generalized solution that is also extendable.
function transform($array, $group=[
['a_id','a_name','b_list'],
['b_id','b_name','c_list'],
['c_id','c_name'],
]){
foreach($array as $a){
$r = &$result;
foreach($group as $g){
$x = &$r[$a[$g[0]]];
$x[$g[0]] = $a[$g[0]];
$x[$g[1]] = $a[$g[1]];
if(isset($g[2])) $r = &$x[$g[2]]; else break;
}
}
return transformResult($result);
}
function transformResult($result){
foreach($result as &$a)
foreach($a as &$b)
if(is_array($b)) $b = transformResult($b);
return array_values($result);
}
To extend this solution, all you have to do is modify the $group parameter,
either directly in the function declaration or by passing an appropriate value as the 2nd parameter.
Usage example:
echo json_encode(transform($array), JSON_PRETTY_PRINT);
This will return the same output assuming the same $array input in your example.
Now here is the code that works best in the given situation. I have created a similar situation and then explained the solution in detail.
Situation
The Order Form is multipage depending on the number of days served based on the package selected. Details of each package are stored in the database with the following fields:
package_id (Unique Field)
package_name (Name of the Package, e.g. Package A)
servings_count (Total Servings in a Day)
days_served (Number of Days Served in a Month)
In order to carry forward the selection of meals for each day and serving of that day to store as an Order in the database, I required a Multidimensional Array of PHP that can be defined/populated dynamically.
Expected output is something like:
Array
(
[Day 1] => Array
(
[meal_id_1] => Unique ID //to be replaced with user selection
[meal_code_1] => Meal Name //to be replaced with user selection
[meal_type_1] => Meal //prefilled based on the selected package
[meal_id_2] => Not Available //to be replaced with user selection
[meal_code_2] => 2 //to be replaced with user selection
[meal_type_2] => Meal //prefilled based on the selected package
)
[Day 2] => Array
(
[meal_id_1] => Unique ID //to be replaced with user selection
[meal_code_1] => Meal Name //to be replaced with user selection
[meal_type_1] => Meal //prefilled based on the selected package
[meal_id_2] => Not Available //to be replaced with user selection
[meal_code_2] => 2 //to be replaced with user selection
[meal_type_2] => Meal //prefilled based on the selected package
)
This above array has been created 100% dynamically based on the explained structure and number of servings and days. Below is the code with some explanation.
First, we have to declare two PHP Arrays.
$total_meals_array = []; //Primary, Multidimension Array
$meals_selected_array = []; //Meals Details Array to be used as primary array's key value.
After doing this, run MySQL query to read packages from the database. Now based on the result, do the following:
$total_meals_array = []; //Primary, Multidimension Array
$meals_selected_array = []; //Meals Details Array to be used as primary array's key value.
if( $num_row_packages >= 1 ) {
while($row_packages = mysqli_fetch_array ($result_packages)) {
$package_id = $row_packages['package_id'];
$package_name = $row_packages['package_name'];
$servings_count = $row_packages['servings_count'];
$days_served = $row_packages['days_served'];
//this for loop is to repeat the code inside `$days_served` number of times. This will be defining our primary and main Multidimensional Array `$total_meals_array`.
for ($y = 1; $y <= $days_served; $y++) {
//once inside the code, now is the time to define/populate our secondary array that will be used as primary array's key value. `$i`, which is the meal count of each day, will be added to the key name to make it easier to read it later. This will be repeated `$meals_count` times.
for ($i = 1; $i <= $meals_count; $i++) {
$meals_selected_array["meal_id_" . $i] = "Unique ID";
$meals_selected_array["meal_code_" . $i] = "Meal Name";
$meals_selected_array["meal_type_" . $i] = "Meal";
}
//once our secondary array, which will be used as the primary array's key value, is ready, we will start defining/populating our Primary Multidimensional Array with Keys Named based on `$days_served`.
$total_meals_array["Day " . $y] = $meals_selected_array;
}
}
}
That's it! Our dynamic Multidimensional Array is ready and can be viewed by simply the below code:
print "<pre>";
print_r($total_meals_array);
print "</pre>";
Thank you everyone, specially #yarwest for being kind enough to answer my question.
Here is the code, you can use it for index from a_ to y_ deep. The innerest element is null, if you don't want it. Terminate the for loop before last element, then process last element seperately. You also can do some improvement on this code. Hope this helps.
<?php
$array = array(
array("a_id" => "1","a_name" => "A1","b_id" => "1","b_name" => "B1","c_id" => "1","c_name" => "C1"),
array("a_id" => "1","a_name" => "A1","b_id" => "1","b_name" => "B1","c_id" => "2","c_name" => "C2"),
array("a_id" => "1","a_name" => "A1","b_id" => "2","b_name" => "B2","c_id" => "3","c_name" => "C3"),
array("a_id" => "2","a_name" => "A2","b_id" => "3","b_name" => "B3","c_id" => "4","c_name" => "C4")
);
$arrays = array_map(function($v){return array_chunk($v, 2, true);}, $array);
$result = [];
foreach($arrays as $value)
{
$ref = &$result;
$len = count($value);
$index = 0;
for(; $index < $len; $index++)
{
$arr = $value[$index];
$char = key($arr)[0];
$charAdd = chr(ord($char)+1);
$key = $arr[$char.'_id'].$arr[$char.'_name'];
$listKey = $charAdd.'_list';
foreach($arr as $k => $v)
{
$ref[$key][$k] = $v;
}
$ref = &$ref[$key][$listKey];
}
}
var_dump($result);
Output: the online live demo
ei#localhost:~$ php test.php
array(2) {
["1A1"]=>
array(3) {
["a_id"]=>
string(1) "1"
["a_name"]=>
string(2) "A1"
["b_list"]=>
array(2) {
["1B1"]=>
array(3) {
["b_id"]=>
string(1) "1"
["b_name"]=>
string(2) "B1"
["c_list"]=>
array(2) {
["1C1"]=>
array(3) {
["c_id"]=>
string(1) "1"
["c_name"]=>
string(2) "C1"
["d_list"]=>
NULL
}
["2C2"]=>
array(3) {
["c_id"]=>
string(1) "2"
["c_name"]=>
string(2) "C2"
["d_list"]=>
NULL
}
}
}
["2B2"]=>
array(3) {
["b_id"]=>
string(1) "2"
["b_name"]=>
string(2) "B2"
["c_list"]=>
array(1) {
["3C3"]=>
array(3) {
["c_id"]=>
string(1) "3"
["c_name"]=>
string(2) "C3"
["d_list"]=>
NULL
}
}
}
}
}
["2A2"]=>
array(3) {
["a_id"]=>
string(1) "2"
["a_name"]=>
string(2) "A2"
["b_list"]=>
array(1) {
["3B3"]=>
array(3) {
["b_id"]=>
string(1) "3"
["b_name"]=>
string(2) "B3"
["c_list"]=>
array(1) {
["4C4"]=>
array(3) {
["c_id"]=>
string(1) "4"
["c_name"]=>
string(2) "C4"
["d_list"]=>
&NULL
}
}
}
}
}
}
This is rather interesting. As far as I can tell, you are trying to transform a flat array into a multidimensional array, as well as transforming the keys into a multidimensional representation.
The top level difference seems to reside in the part before the underscore of the a_* keys.
Then, for each of these keys, every other *_ letters should induce it's own list.
This recursive function does the trick without hardcoding, will work with whatever number of levels, letters (or whatever else) and right identifiers.
It seems to return exactly the json you show in the sample ($array being the array as defined in your question)
$multidimension = multidimensionalify($array, ['a', 'b', 'c'], ['name']);
var_dump(json_encode($multidimension, JSON_PRETTY_PRINT));
function multidimensionalify(
array $input,
array $topLevelLetters,
array $rightHandIdentifiers,
$level = 0,
$parentId = null,
$uniqueString = 'id'
)
{
$thisDimension = [];
$thisLetter = $topLevelLetters[$level];
foreach ($input as $entry)
{
$thisId = $entry["{$thisLetter}_{$uniqueString}"];
$condition = true;
if ($parentId !== null)
{
$parentLetter = $topLevelLetters[$level - 1];
$condition = $entry["{$parentLetter}_{$uniqueString}"] === $parentId;
}
if (!isset($thisDimension[$thisId]) && $condition)
{
$thisObject = new stdClass;
$thisObject->{"{$thisLetter}_{$uniqueString}"} = $thisId;
foreach ($rightHandIdentifiers as $identifier)
{
$thisObject->{"{$thisLetter}_{$identifier}"} = $entry["{$thisLetter}_{$identifier}"];
}
if (isset($topLevelLetters[$level + 1])) {
$nextLetter = $topLevelLetters[$level + 1];
$thisObject->{"{$nextLetter}_list"} = multidimensionalify($input, $topLevelLetters, $rightHandIdentifiers, $level + 1, $thisId, $uniqueString);
}
$thisDimension[$thisId] = $thisObject;
}
}
return array_values($thisDimension);
}
Try this function just pass your array and key name for grouping and then convert to json.
public function _group_by($array, $key) {
$return = array();
foreach ($array as $val) {
$return[$val[$key]][] = $val;
}
return $return;
}
I'm retriving data from mysql. in my php I've got 2 arrays set
$main =array(); //tostore retrived data
$list =array('instock' => 'output1', 'item' => 'output2'); //existing key values and new key value to be replaced
How do I replace the keys with custom keys for each output? exmpale: custom keys output1,output2
current output
[{"instock":"yes", "item":"ch00024"},{..}]
Expected output
[{"output1":"yes", "output2":"ch00024"},{..}]
This is what I have tried so far. But does not work.
$main =array(); //tostore retrived data
$list =array('instock' => 'output1', 'item' => 'output2'); //replace key values
foreach ($result as $key => $value){
$main[ $list[ $key ] ] = $value;
}
echo json_encode( $main );
I get an error Undefined offset: 0. It points to this line $main[ $list[ $key ] ] = $value;
EDIT
This is a screen capture from my console
var_dump():
array(5) {
[0]=>
array(2) {
["instock"]=>
string(3) "yes"
["item"]=>
string(6) "it0215"
}
[1]=>
array(2) {
["instock"]=>
string(3) "yes"
["item"]=>
string(6) "it0381"
}
so on...
Your code works! The issue is in $list array you need define all keys in $result otherwise you need to check if there is that key in $list array.
$result =array(
'instock' => 'yes',
'item' => 'ch00024',
'color' => 'blue',
'price' => 100
);
$main = array();
$list = array('instock' => 'output1', 'item' => 'output2');
foreach ($result as $key => $value){
if (!empty($list[$key])) {
$main[$list[$key]] = $value;
}
}
echo json_encode($main);
Edit
Because you are access 2 dimensional array, so you need an extra loop to go through all items
$result = array(
array (
'instock' => 'yes',
'item' => 'it0215'
),
array(
'instock' => 'yes',
'item' => 'it0381'
)
);
$main = array();
$list = array('instock' => 'output1', 'item' => 'output2');
foreach ($result as $item){
foreach ($item as $key => $value) {
$main[$list[$key]] = $value;
}
}
echo json_encode($main);
The output is
{"output1":"yes","output2":"it0381"}
But In case you want to get all items with key replacement in new array. You should do something like this:
foreach ($result as $index => $item){
foreach ($item as $key => $value) {
$main[$index][$list[$key]] = $value;
}
}
echo json_encode($main);
The output is:
[
{"output1":"yes","output2":"it0215"},
{"output1":"yes","output2":"it0381"}
]
try to this code
$flippedList = array_flip($list);
I want to iterate over a multidimensional array, count the occurrences of a String inside and delete Array items where the count is higher than e.g. 3.
I've already tried a pretty messy combination of array_search, array_count_values and strpos inside a N^N loop, but this takes way to long to process and the results are wrong...
This is the Array, I'm trying to alter
array(2) {
[0]=>
array(13) {
["id"]=>
string(6) "1234"
["name"]=>
string(28) "aa"
["productcategory"]=>
string(30) "Branch1^^subbranch1"
["streamID"]=>
int(0)
["streamContext"]=>
string(16) "static"
["prio"]=>
string(3) "100"
}
[1]=>
array(11) {
["id"]=>
string(6) "9876"
["name"]=>
string(30) "bb"
["productcategory"]=>
string(66) "Branch1^^subbranch2"
["streamID"]=>
int(0)
["streamContext"]=>
string(16) "static"
["prio"]=>
string(3) "100"
}
}
The surrounding Array can have around 200 Items. I'm looking for a way to remove Items if theyr productcategory is found more than X times.
Can you guys help me with this?
Yeah I've had to deal with something kind of similar. If you're looking at an array of around 200, then it should be too slow to create a counter loop and then unset the values of the original array based on those counters. I've provided a template to think about, to see if this is the direction you're after.
It makes a copy of the array, then counts the productcategory, of course I'm assuming that category^^subcategory is the count you are looking for.
<?php
$your_array = array(
array(
array(
"id" => "1234",
"name" => "aa",
"productcategory" => "Branch1^^subbranch1",
"streamID" => '',
"streamContext" => "static",
"prio" => "100",
),
array(
"id" => "9876",
"name" => "bb",
"productcategory" => "Branch1^^subbranch1",
"streamID" => '',
"streamContext" => "static",
"prio" => "100",
),
array(
"id" => "9876",
"name" => "bb",
"productcategory" => "Branch1^^subbranch3",
"streamID" => '',
"streamContext" => "static",
"prio" => "100",
),
array(
"id" => "9876",
"name" => "bb",
"productcategory" => "Branch1^^subbranch2",
"streamID" => '',
"streamContext" => "static",
"prio" => "100",
),
array(
"id" => "9876",
"name" => "bb",
"productcategory" => "Branch1^^subbranch3",
"streamID" => '',
"streamContext" => "static",
"prio" => "100",
),
array(
"id" => "9876",
"name" => "bb",
"productcategory" => "Branch1^^subbranch1",
"streamID" => '',
"streamContext" => "static",
"prio" => "100",
),
),
);
$counters = array();
$limit = 1; // whatever the limit is that you want
foreach ($your_array as $index => $array) {
for ($i = 0; $i < count($array); $i++) {
if (!isSet($counters[$array[$i]['productcategory']])) {
$counters[$array[$i]['productcategory']] = 0;
}
$counters[$array[$i]['productcategory']]++;
if ($counters[$array[$i]['productcategory']] > $limit) {
unset($your_array[$index][$i]);
}
}
}
print '<pre>' . print_r($counters, true) . '</pre>';
print '<pre>' . print_r($your_array, true) . '</pre>';
I'm unsetting that item in the sub array, as I'm not sure if you want to just unset the whole item.
My first question for you would be "where is your data coming from?" If this is coming out of a database, then I would recommend you tweak your query there. You can definitely solve this in PHP, but as your data set grows it will take longer and longer to loop over the dataset in PHP.
To solve this in PHP, I would recommend you create a new "product index" array. This array would be associative with the product name as the keys and the values would contain an array of all the top-level indexes in your dataset array. Once you've built the index array, you can loop over that to find which product types occur more than 3 times in the main dataset and quickly delete those items.
$productIndex = [];
// Build an index of product categories
foreach($dataset as $i => $row) {
if (!is_array($productIndex[$row['productcategory']]) {
$productIndex[$row['productcategory']] = [];
}
$productIndex[$row['productcategory']][] = $i;
}
// Search for indexes with > 3 rows
foreach($productIndex as $items) {
if (count($items) > 3) {
// Delete said rows
foreach ($items as $index) {
unset($dataset[$index]);
}
}
}
I havent been able to use a one size fits it all approach, but for future reference i will share my "solution". It doesnt feel like super sophisiticated but it gets the job done...
function filter_categories($input, $count) {
$output = $input;
$exploded_input = [];
foreach ($output as $key => $value) {
$exploded_items = explode("^^", $value["productcategory"]);
array_push($exploded_input, $exploded_items);
}
$sortedbyCategory = [];
$last_items = [];
$counted_items = [];
foreach ($exploded_input as $key => $value) {
$end = end($value);
array_push($last_items, $end);
}
$counted = array_count_values($last_items);
foreach ($counted as $key => $value) {
if($value<=$count) {
unset($counted[$key]);
}
}
foreach ($counted as $k => $v) {
for ($i=0; $i < count($input); $i++) {
if(strpos($input[$i]["productcategory"], $k)){
if($counted[$k] > $count) {
$input[$i]["hide"] = true;
$counted[$k]--;
}
}
}
}
foreach ($input as $key => $value) {
if(isset($value["hide"])) {
unset($input[$key]);
}
}
return $input;
}