If I have this array -
$data_item['actor_id'] = $this->input->post('actor_id');
$data_item['item_number'] = $this->input->post('item_number');
Which gives me this array -
Array (
[actor_id] => Array (
[0] => 162652153
[1] => 162652154
)
[item_number] => Array (
[0] => 3
[1] => 6
)
)
I need to get my data into this format -
$data = array(
array(
'actor_id' => '3342' ,
'item_number' => '57567'
),
array(
'actor_id' => '876' ,
'item_number' => '94'
)
);
I have tried various ways of looping through it but I can't seem to get it. Such as two seperate loops like this -
foreach($data_item['actor_id'] as $key => $value){
$thevalue[] = array('actor_id' => $value
);
}
But it is wrong format. Any tips please?
What about:
$d = [
'actor_id' => [
1,
2,
],
'item_number' => [
3,
4,
],
];
$res = [];
foreach ( $d as $key => $data ) {
foreach ( $data as $index => $value ) {
$res [ $index ] [$key] = $value;
}
}
I'll generate:
array(2) {
[0]=>
array(2) {
["actor_id"]=>
int(1)
["item_number"]=>
int(3)
}
[1]=>
array(2) {
["actor_id"]=>
int(2)
["item_number"]=>
int(4)
}
}
HTH
you can make use of the actor_id keys to flatten your data as desired:
$data = array(); // your new array
foreach($data_item['actor_id'] as $key => $value) {
// make sure we have an array for this key and add actor id
if (!isset($data[$key])) $data[$key] = array();
$data[$key]['actor_id'] = $value;
// now check if we have an item number for this key and add it
if (isset($data_item['item_number'][$key]))
$data[$key]['item_number'] = $data_item['item_number'][$key];
}
print_r($data);
The result should print out just as you wanted it. Sorry for not having tested the code my self, just typed it out of my head missing time and interpreter right now :)
Related
I need to extract data from elements with keys that start with foo. from the below array:
[
'name' => 'Bar',
'location' => 'Baz',
'foo.2021-02-01' => '50000.00',
'foo.2021-03-01' => '50000.00',
'foo.2021-04-01' => '50000.00',
'foo.2021-05-01' => '',
]
After identifying qualifying keys, I need to create a new indexed array of associative rows using the date substring from the original keys like so:
[
['date' => '2021-02-01', 'value' => '50000.00'],
['date' => '2021-03-01', 'value' => '50000.00'],
['date' => '2021-04-01', 'value' => '50000.00'],
['date' => '2021-05-01', 'value' => ''],
]
I've been able to extract the keys like so:
$keys = array_keys($theData[0]);
foreach ( $keys as $key ) {
if ( preg_match( '/foo.*/', $key ) ) {
$line = explode('.', $key);
$item[]['name'] = $line[1];
}
}
but I'm losing the values.
I then tried looping through the array manually and rebuilding the desired outcome, but the keys will change so I don't know how future-proof that would be.
Is there a wildcard approach I can take to achieve this?
You almost had it:
<?php
$theData = [
'name' => 'Bar',
'location' => 'Baz',
'foo.2021-02-01' => '50000.00',
'foo.2021-03-01' => '50000.00',
'foo.2021-04-01' => '50000.00',
'foo.2021-05-01' => ''
];
$item = [];
// No need for array_keys(), foreach() can already do this
foreach( $theData as $key => $value )
{
// check if the key starts with foo.
// Regular expressions are heavy; if you'd like then substitute with:
// if ( substr( $key, 0, 4 ) === 'foo.' )
if ( preg_match( '/^foo\\./', $key ) )
{
// foo. is 4 chars long so substring from the fourth index till the end
$item[] = [
'date' => substr( $key, 4 ),
'value' => $value
];
}
}
var_dump( $item );
Output:
array(4) {
[0]=>
array(2) {
["date"]=>
string(10) "2021-02-01"
["value"]=>
string(8) "50000.00"
}
[1]=>
array(2) {
["date"]=>
string(10) "2021-03-01"
["value"]=>
string(8) "50000.00"
}
[2]=>
array(2) {
["date"]=>
string(10) "2021-04-01"
["value"]=>
string(8) "50000.00"
}
[3]=>
array(2) {
["date"]=>
string(10) "2021-05-01"
["value"]=>
string(0) ""
}
}
A simple loop, checking for the key starting with foo. and then a little code to replace foo. in the key with nothing will do the trick
If you have PHP8 or >
$arr = [
'name' => 'Bar',
'location' => 'Baz',
'foo.2021-02-01' => '50000.00',
'foo.2021-03-01' => '50000.00',
'foo.2021-04-01' => '50000.00',
'foo.2021-05-01' => ''
];
$new = [];
foreach ($arr as $k => $v){
if ( str_starts_with( $k , 'foo.' ) ) {
$new[] = ['date' => str_replace('foo.', '', $k), 'value' => $v];
}
}
print_r($new);
RESULT
Array
(
[0] => Array
([date] => 2021-02-01, [value] => 50000.00)
[1] => Array
([date] => 2021-03-01, [value] => 50000.00)
[2] => Array
([date] => 2021-04-01, [value] => 50000.00)
[3] => Array
([date] => 2021-05-01, [value] => )
)
Alternatively, for PHP versions prior to PHP8
$new = [];
foreach ($arr as $k => $v){
if ( strpos( $k , 'foo.') !== FALSE && strpos( $k , 'foo.') == 0 ) {
$new[] = ['date' => str_replace('foo.', '', $k), 'value' => $v];
}
}
Using str_starts_with and explode
$arr = [];
foreach ($theData as $k => $v){
if (str_starts_with($k, "foo."))
$arr[] = ["date" => explode(".", $k)[1], "value" => $v];
}
var_dump($arr);
sscanf() is an ideal function to call which will both check for qualifying strings and extract the desired trailing date value. It doesn't use regex, but it does require a placeholder %s to target the date substring. If a given string doesn't qualify, no element is pushed into the result array.
Code: (Demo) (without compact())
$result = [];
foreach ($array as $key => $value) {
if (sscanf($key, 'foo.%s', $date)) {
// $result[] = ['date' => $date, 'value' => $value];
$result[] = compact(['date', 'value']);
}
}
var_export($result);
If you remove the optional technique of using compact(), this solution makes fewer function calls than all other answers on this page.
I would probably only use regex if I wanted to strengthen the validation for qualifying key strings. (Demo)
$result = [];
foreach ($array as $key => $value) {
if (preg_match('~^foo\.\K\d{4}-\d{2}-\d{2}$~', $key, $m)) {
$result[] = ['date' => $m[0], 'value' => $value];
}
}
var_export($result);
I have an array like this:
array(
[cat] => news,
[comments_count] => 2,
[meta] => array(
[first_meta] => 44,
[second_meta] => 54,
)
)
The above code is an example of array that I have. Now I wanna make the above array clear like this:
array(
[cat] => news,
[comments_count] => 2,
[first_meta] => 44,
[second_meta] => 54,
)
(means Delete -meta- but not it's indexes. I want to add indexes of meta to the first array)
Add the meta array to the array and then unset the meta array:
$array = $array + $array['meta'];
unset($array['meta']);
You may use the below function if you have a multidimentional array and you can reuse it anywhere.
function array_flatten($array) {
if (!is_array($array)) {
return false;
}
$result = array();
foreach ($array as $key => $value) {
if (is_array($value)) {
$result = array_merge($result, array_flatten($value));
} else {
$result[$key] = $value;
}
}
return $result;
}
$array = array(
'cat' => 'news',
'comments_count' => '2',
'meta' => array(
'first_meta' => '44',
'second_meta' => '54',
)
);
var_dump(array_flatten($array));
The result will be
array(4) {
["cat"]=>
string(4) "news"
["comments_count"]=>
string(1) "2"
["first_meta"]=>
string(2) "44"
["second_meta"]=>
string(2) "54"
}
Otherwise if you just need to flatten meta array as in your question. array_merge() the meta array and unset meta it as below.
$result = array_merge($array, $array["meta"]);
unset($result["meta"]);
var_dump($result);
Please help me on how to count the occurrences of value in this associative array.
<?php
$employees = array(
1 => array(
'name' => 'Jason Alipala',
'employee_id' => 'G1001-05',
'position' => 1
),
2 => array(
'name' => 'Bryann Revina',
'employee_id' => 'G1009-03',
'position' => 2
),
3 => array(
'name' => 'Jeniel Mangahis',
'employee_id' => 'G1009-04',
'position' => 2
),
4 => array(
'name' => 'Arjay Bussala',
'employee_id' => 'G1009-05',
'position' => 3
),
5 => array(
'name' => 'Ronnel Ines',
'employee_id' => 'G1002-06',
'position' => 3
)
);
?>
This is my code from fake_db.php which I include_once in the index.php. I want to count the occurrences of the same value of 'position'.. e.g. 1 = 1, 2 = 2, 3 = 2
in addition, there is another array named $positions...
$positions = array(
1 => 'TL',
2 => 'Programmer',
3 => 'Converter');
this array is where i compare the 'position' from the $employees array.
any help is appreciated, thank you!
Combination of array_count_values & array_column (PHP 5 >= 5.5.0, PHP 7) should work -
$counts = array_count_values(
array_column($employees, 'position')
);
Output
array(3) {
[1]=>
int(1)
[2]=>
int(2)
[3]=>
int(2)
}
Update
$final = array_filter($counts, function($a) {
return $a >= 2;
});
Output
array(2) {
[2]=>
int(2)
[3]=>
int(2)
}
Demo
array_column — Return the values from a single column of array. array_count_values — Counts all the values of an array.
$positions = array_column($employees, 'position');
print_r(array_count_values($positions));
Output
Array
(
[1] => 1
[2] => 2
[3] => 2
)
Nested loop will do the job. Take an array, keep the key as the actual value and the value in the key as COUNTER of that key.
if the key exists in array that means it has the value just increment else assign 1 to initialize the key with value 1.
e.g. 1=>counter of 1 (occurrences)
$arrayCounter=0;
foreach($employees as $value){
foreach($value as $data){
$position = $data['position'];
if(array_key_exists($position,$arrayCounter)){
$arrayCounter[$position] = arrayCounter[$position]++;
}
else{
$arrayCounter[$position] = 1;
}
}
It is pretty simple. The array $employees is the array you have supplied. You can use this code:
$data = array();
foreach($employees as $employee) {
if(isset($data[$employee['position']])) {
$data[$employee['position']]++;
} else {
$data[$employee['position']] = 1;
}
}
echo "<pre>";
print_r($data);
echo "</pre>";
This gives the output:
Array
(
[1] => 1
[2] => 2
[3] => 2
)
You can use array_count_value() pre-define php function to get your aim.
you can see result here
$total = 0;
foreach($employees as $eNum => $value){
if($aEmployees[$eNum]['position'] == $key){
$total++;
}
}
echo $total;
These codes are inside a function that is called on every iteration of a foreach loop(another array named '$positions')..
$key is a variable that contains value from that foreach loop (the '$positions' array).. this is what I've done, and it works for me. But i don't know if this is the proper way?
I have an array that looks like this:
[0] => Array
(
[name] => typeOfMusic
[value] => this_music_choice
)
[1] => Array
(
[name] => myMusicChoice
[value] => 9
)
[2] => Array
(
[name] => myMusicChoice
[value] => 8
)
I would like to reform this into something with roughly the following structure:
Array(
"typeOfMusic" => "this_music_choice",
"myMusicChoice" => array(9, 8)
)
I have written the following but it doesn't work:
foreach($originalArray as $key => $value) {
if( !empty($return[$value["name"]]) ){
$return[$value["name"]][] = $value["value"];
} else {
$return[$value["name"]] = $value["value"];
}
}
return $return;
I've tried lots of different combinations to try and get this working. My original array could contain several sets of keys that need converting to arrays (i.e. it's not always going to be just "myMusicChoice" that needs converting to an array) ?
I'm getting nowhere with this and would appreciate a little help. Many thanks.
You just need to loop over the data and create a new array with the name/value. If you see a repeat name, then change the value into an array.
Something like this:
$return = array();
foreach($originalArray as $data){
if(!isset($return[$data['name']])){
// This is the first time we've seen this name,
// it's not in $return, so let's add it
$return[$data['name']] = $data['value'];
}
elseif(!is_array($return[$data['name']])){
// We've seen this key before, but it's not already an array
// let's convert it to an array
$return[$data['name']] = array($return[$data['name']], $data['value']);
}
else{
// We've seen this key before, so let's just add to the array
$return[$data['name']][] = $data['value'];
}
}
DEMO: https://eval.in/173852
Here's a clean solution, which uses array_reduce
$a = [
[
'name' => 'typeOfMusic',
'value' => 'this_music_choice'
],
[
'name' => 'myMusicChoice',
'value' => 9
],
[
'name' => 'myMusicChoice',
'value' => 8
]
];
$r = array_reduce($a, function(&$array, $item){
// Has this key been initialized yet?
if (empty($array[$item['name']])) {
$array[$item['name']] = [];
}
$array[$item['name']][] = $item['value'];
return $array;
}, []);
$arr = array(
0 => array(
'name' => 'typeOfMusic',
'value' => 'this_music_choice'
),
1 => array(
'name' => 'myMusicChoice',
'value' => 9
),
2 => array(
'name' => 'myMusicChoice',
'value' => 8
)
);
$newArr = array();
$name = 'name';
$value = 'value';
$x = 0;
foreach($arr as $row) {
if ($x == 0) {
$newArr[$row[$$name]] = $row[$$value];
} else {
if (! is_array($newArr[$row[$$name]])) {
$newArr[$row[$$name]] = array();
}
array_push($newArr[$row[$$name]], $row[$$value]);
}
$x++;
}
I have an array which looks like this
$dataArray = array (
0 =>
array (
'UserId' => '804023',
'ProjectCode' => 'RA1234',
'Role' => 'PI',
),
1 =>
array (
'UserId' => '804023',
'ProjectCode' => 'RA1234',
'Role' => 'PM',
),
2 =>
array (
'UserId' => '804023',
'ProjectCode' => 'A90123',
'Role' => 'CI',
),
3 =>
array (
'UserId' => '804023',
'ProjectCode' => 'A20022',
'Role' => 'PM',
),
)
I need it to look like this
$expected = array (
804023 =>
array (
'RA1234' =>
array (
0 => 'PI',
1 => 'PM',
),
'A90123' =>
array (
0 => 'PI',
),
'A20022' =>
array (
0 => 'CI',
),
),
)
I think this could be achieved generically using recursion as this is a scenario I am likely to come across many times
I have got this far passing in an array of keys that form the nested array keys i.e.
$keys=array("UserId","projectCode","Role");
but am just not seeing where to go from here any pointers?
public function structureData(array $data, array $keys)
{
//$structuredData = array();
foreach ($data as $key => $value)
{
$keyForData = array_slice($keys,0,1);
$remainingKeys = $keys;
array_shift($remainingKeys);
if (!array_key_exists($value[$keyForData[0]], $structuredData))
{
$count=count($remainingKeys);
$structuredData[$value[$keyForData[0]]] =array();
// this returns as expected array(804023 =>array ()); but subsequent recursive calls with the remaining data fail
}
}
return $structuredData);
}
You don't need recursion, just a loop:
foreach ($dataArray as $da) {
$expected[$da['UserId']][$da['ProjectCode']][] = $da['Role'];
}
var_export($expected);
/* output:
array (
804023 =>
array (
'RA1234' =>
array (
0 => 'PI',
1 => 'PM',
),
'A90123' =>
array (
0 => 'CI',
),
'A20022' =>
array (
0 => 'PM',
),
),
)
*/
A crude but functioning solution.
function structureData($data, $keys){
$out = array();
foreach($data as $row){
$subout = &$out;
foreach(array_slice($keys, 0, -1) as $key){
$value = $row[$key];
$subout = &$subout[$value];
}
$subout[] = $row[$keys[count($keys) - 1]];
}
return $out;
}
print_r(structureData($dataArray, array('UserId', 'ProjectCode', 'Role')));
Recursion? Nah. Try this:
function add_role($dataArray, $userid, $project_code, $role)
{
$dataArray[$userid][$project_code][] = $role;
}
Functional solution:
$t = array_gather_key($dataArray, function ($e) { return $e['UserId']; } );
$t = array_map(
function ($e) {
return array_gather_key($e,
function ($e) { return $e['ProjectCode']; },
function ($e) { return $e['Role']; } );
},
$t
);
With this higher-order function:
function array_gather_key($array, $func, $transf = null) {
$res = array();
foreach ($array as $elem) {
$key = $func($elem);
if (!array_key_exists($key, $res))
$res[$key] = array();
if ($transf === null)
$res[$key][] = $elem;
else
$res[$key][] = $transf($elem);
}
return $res;
}
This gives:
array(1) {
[804023]=>
array(3) {
["RA1234"]=>
array(2) {
[0]=>
string(2) "PI"
[1]=>
string(2) "PM"
}
["A90123"]=>
array(1) {
[0]=>
string(2) "CI"
}
["A20022"]=>
array(1) {
[0]=>
string(2) "PM"
}
}
}