PHP Array duplicate data count - php

I have title and language data in PHP Array. I need to display repeated title count. Please check below array format.
Array (
[0] => Array ( [title] => My_title1 [language] => English )
[1] => Array ( [title] => My_title1 [language] => English )
[2] => Array ( [title] => My_title2 [language] => Japanese )
)
I need to display data in following format.
Title Language Count
My_title1 English 2
My_title2 Japanese 1
I tried following code
$count = array_count_values(array_map(
function($item) {
return $item['title'];
}, $testArray));
print_r($count);
but I got only title counts.
Array ( [My_title1] => 2 [My_title2] => 1 )
How do I display like following format?
Title Language Count
My_title1 English 2
My_title2 Japanese 1

You can do it for example this way:
<?php
$testArray = array (
0 => Array ( 'title' => 'My_title1', 'language' => 'English' ),
1 => Array ( 'title' => 'My_title1', 'language' => 'English' ),
2 => Array ( 'title' => 'My_title2', 'language' => 'Japanese' ),
);
$count = array_count_values(array_map(
function($item) {
return $item['title'].'#'.$item['language'];
}, $testArray));
$outArray = array();
foreach ($count as $k => $v) {
$k = explode('#', $k);
$record['Title'] = $k[0];
$record['Language'] = $k[1];
$record['Count'] = $v;
$outArray[] = $record;
}
var_dump($outArray);
Of course you need to use character that will not be used inside title and language, probably # is quite good enough

Try this code code which i created just for this assignment
<?php
$array = array(
0 => array ( 'title' => 'My_title1', 'language' => 'English'),
1 => array ( 'title' => 'My_title1', 'language' => 'English'),
2 => array ( 'title' => 'My_title2', 'language' => 'Japanese')
);
$final = array();
foreach($array as $key =>$value)
{
$flag = 0;
foreach($final as $key1 =>$value1)
{
if($array[$key]['title'] == $final[$key1]['title'])
{
$final[$key1]['count']++;
$flag = 1;
}
}
if($flag == 0)
{
$push = array('title' => $array[$key]['title'],'language' => $array[$key]['language'],'count' =>1);
array_push($final,$push);
}
}
echo "<pre>";print_r($final);

Related

Adding to another array with triming few characters from string

$data has
stdClass Object
(
[class] => srt-fields
[rules_field_1] => 1
[rules_condition_1] => 0
[rules_value_1] => text
[rules_field_2] => 3
[rules_condition_2] => 1
[rules_value_2] => another_text
...
)
Now I have another array $newdata, I need to have index $newdata['rules'] so that it should be something like:
$newdata['rules'] => array(
[field] => 1,
[condition] => 0,
[value] => text
),
array(
[field]=> 3,
[condition] =>1,
[value] => another_text
),
...
Thanks!
You could iterate over the properties of an object like an array:
$newdata['rules']=[];
foreach ($data as $key => $value) {
if (substr($key,0,6)=='rules_') {
// split key using '_'
$parts = explode('_',$key);
// get the 'name'
$name = $parts[1] ;
// get the index (-1 to be 0 based)
$idx = $parts[2] - 1;
// store data in new array
$newdata['rules'][$idx][$name] = $value;
}
}
print_r($newdata);
Outputs:
Array
(
[rules] => Array
(
[0] => Array
(
[field] => 1
[condition] => 0
[value] => text
)
[1] => Array
(
[field] => 3
[condition] => 1
[value] => another_text
)
)
)
Here is working code,
$data = [
"class" => "srt-fields",
"rules_field_1" => "1",
"rules_condition_1" => "0",
"rules_value_1" => "text",
"rules_field_2" => "3",
"rules_condition_2" => "1",
"rules_value_2" => "another_text",
];
$result = [];
foreach ($data as $k => $v) {
$num = filter_var($k, FILTER_SANITIZE_NUMBER_INT);
if (!empty($num)) {
$result['rules'][$num][(str_replace(['rules_', '_'], '', preg_replace('/[0-9]+/', '', $k)))] = $v;
}
}
$result['rules'] = array_values($result['rules']);
print_r($result);
str_replace — Replace all occurrences of the search string with the replacement string
filter_var — Filters a variable with a specified filter
preg_replace — Perform a regular expression search and replace
str_replace — Replace all occurrences of the search string with the replacement string
Here is working demo.
Definitely do not use regular expressions for this task -- because it is unnecessary resource overhead. Explode the keys on underscores, and use the individual components to construct the multi-level keys in your output array.
Code: (Demo)
$data = (object)[
"class" => "srt-fields",
"rules_field_1" => "1",
"rules_condition_1" => "0",
"rules_value_1" => "text",
"rules_field_2" => "3",
"rules_condition_2" => "1",
"rules_value_2" => "another_text"
];
foreach ($data as $key => $value) {
$bits = explode('_',$key); // this will produce a 1-element array from `class` and a 3-element array from others
if (isset($bits[2])) { // if element [2] exists, then process the qualifying data
$newdata[$bits[0]][$bits[2]-1][$bits[1]] = $value;
// ^^- make zero based
}
}
var_export($newdata);
Output:
array (
'rules' =>
array (
0 =>
array (
'field' => '1',
'condition' => '0',
'value' => 'text',
),
1 =>
array (
'field' => '3',
'condition' => '1',
'value' => 'another_text',
),
),
)
I am using -1 to make the output keys resemble a zero-based / indexed array. If your fields might not be consecutively ordered, you can remove the -1 and write $newdata['rules'] = array_values($newdata['rules']); after the loop.
$i = 0;
$j = 0;
foreach($data as $key=>$value){
if($j == 0)
{
$newdata['rules'][$i]['field'] = $value;
}
if($j == 1)
{
$newdata['rules'][$i]['condition'] = $value;
}
if($j == 2)
{
$newdata['rules'][$i]['value'] = $value;
$i++;
}
$j++;
if($j > 2)
{
$j = 0;
}
}
You can try this code. Please ignore syntax error as I have not tried this code but it should give you the result.

How to merge an array with child elements

I have an array with same customerid. I want to merge all same customerid arrays in to one with few amends to the array.
Array
(
[0] => Array
(
[customerid] => 13
[customer_fullname] => Chris
[profession_id] => 8
[profession_name] => Producer
)
[1] => Array
(
[customerid] => 1
[customer_fullname] => John
[profession_id] => 8
[profession_name] => Producer
)
[2] => Array
(
[customerid] => 13
[customer_fullname] => Chris
[profession_id] => 7
[profession_name] => Camera
)
)
So now I want a new array to be created like this:
Array(
[customerid] => 13
[customer_fullname] => Chris
[new_array] => array(
[0]=>[profession_id] => 8, [profession_name] => Producer,
[1]=>[profession_id] => 7, [profession_name] => Camera
)
)
Spent some time on it but wasn't able to get it right
There are better approaches if you're merging lots of records, but if you want a way to just merge two records as stated, I'd just do this:
$array1 = array(
'customerid' => 13
'customer_fullname' => 'John',
'profession_id' => 8,
'profession_name' => 'Producer'
);
$array2 = array(
'customerid' => 13
'customer_fullname' => 'John',
'profession_id' => 7,
'profession_name' => 'Director'
);
function merge_customers($customerA, $customerB)
{
$newCustomer = array();
if ($customerA['customerid'] == $customerB['customerid'])
{
$newCustomer['customerid'] = $customerA['customerid'];
$newCustomer['customer_fullname'] = $customerA['customer_fullname'];
$newCustomer['new_array'] = array(
array(
'profession_id' => $customerA['profession_id'],
'profession_name' => $customerA['profession_name']
),
array(
'profession_id' => $customerB['profession_id'],
'profession_name' => $customerB['profession_name']
)
);
return $newCustomer;
}
/* We can't merge these if they're different customers. */
return NULL;
}
The extended solution which is also well-suited for finding and "merging" multiple groups of entries which has same customerid. Used functions: array_filter, array_count_values, array_keys, array_walk, array_chunk and array_values:
// supposing $arr is your initial array
// finds which 'customerid' has multiple entries
$dupIds = array_filter(array_count_values(array_column($arr, "customerid")), function($v) {
return $v > 1;
});
$dupIds = array_keys($dupIds);
$result = [];
array_walk($arr, function($v) use(&$result, $dupIds) {
if (in_array($v['customerid'], $dupIds)) {
$parts = array_chunk($v, 2, true);
if (!isset($result[$v['customerid']])) {
$result[$v['customerid']] = $parts[0] + ['new_array' => [$parts[1]]];
} else {
$result[$v['customerid']]['new_array'][] = $parts[1];
}
}
});
print_r(array_values($result));
The output:
Array
(
[0] => Array
(
[customerid] => 13
[customer_fullname] => Chris
[new_array] => Array
(
[0] => Array
(
[profession_id] => 8
[profession_name] => Producer
)
[1] => Array
(
[profession_id] => 7
[profession_name] => Camera
)
)
)
)
Quick hack, maybe there is a nicer solution.
Note: The second "for each" loop is only needed if there is the possibility that the arrays don't have the same fields.
function merge($array1, $array2){
$result = array();
foreach($array1 as $key => $value){
if(isset($array2[$key]) && $array2[$key]!=$array1[$key]){
$result[$key][]=$value;
$result[$key][]=$array2[$key];
}else{
$result[$key]=$value;
}
}
foreach($array2 as $key => $value){
if(!isset($result[$key])){
$result[$key] = $value;
}
}
return $result;
}
print_r(merge($array1, $array2));

PHP Counting inside an Array

I want to create a list where if its already in the array to add to the value +1.
Current Output
[1] => Array
(
[source] => 397
[value] => 1
)
[2] => Array
(
[source] => 397
[value] => 1
)
[3] => Array
(
[source] => 1314
[value] => 1
)
What I want to Achieve
[1] => Array
(
[source] => 397
[value] => 2
)
[2] => Array
(
[source] => 1314
[value] => 1
)
My current dulled down PHP
foreach ($submissions as $timefix) {
//Start countng
$data = array(
'source' => $timefix['parent']['id'],
'value' => '1'
);
$dataJson[] = $data;
}
print_r($dataJson);
Simply use an associated array:
$dataJson = array();
foreach ($submissions as $timefix) {
$id = $timefix['parent']['id'];
if (!isset($dataJson[$id])) {
$dataJson[$id] = array('source' => $id, 'value' => 1);
} else {
$dataJson[$id]['value']++;
}
}
$dataJson = array_values($dataJson); // reset the keys - you don't nessesarily need this
This is not exactly your desired output, as the array keys are not preserved, but if it suits you, you could use the item ID as the array key. This would simplify your code to the point of not needing to loop through the already available results:
foreach ($submissions as $timefix) {
$id = $timefix['parent']['id'];
if (array_key_exists($id, $dataJson)) {
$dataJson[$id]["value"]++;
} else {
$dataJson[$id] = [
"source" => $id,
"value" => 1
];
}
}
print_r($dataJson);
You should simplify this for yourself. Something like:
<?
$res = Array();
foreach ($original as $item) {
if (!isset($res[$item['source']])) $res[$item['source']] = $item['value'];
else $res[$item['source']] += $item['value'];
}
?>
After this, you will have array $res which will be something like:
Array(
[397] => 2,
[1314] => 1
)
Then, if you really need the format specified, you can use something like:
<?
$final = Array();
foreach ($res as $source=>$value) $final[] = Array(
'source' => $source,
'value' => $value
);
?>
This code will do the counting and produce a $new array as described in your example.
$data = array(
array('source' => 397, 'value' => 1),
array('source' => 397, 'value' => 1),
array('source' => 1314, 'value' => 1),
);
$new = array();
foreach ($data as $item)
{
$source = $item['source'];
if (isset($new[$source]))
$new[$source]['value'] += $item['value'];
else
$new[$source] = $item;
}
$new = array_values($new);
PHP has a function called array_count_values for that. May be you can use it
Example:
<?php
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));
?>
Output:
Array
(
[1] => 2
[hello] => 2
[world] => 1
)

counting occurence on multiple PHP array [duplicate]

This question already has answers here:
Count specific values in multidimensional array
(4 answers)
Closed 9 years ago.
I'm looking for a way to count occurence on an array of array.
This is my array :
Array
(
[0] => Array
(
[id] => 671
[title] => BIEND
[img] =>
[ville] => marseille
)
[1] => Array
(
[id] => 670
[title] => BIENC
[img] =>
[ville] => avignon
)
[2] => Array
(
[id] => 669
[title] => BIENB
[img] =>
[ville] => avignon
)
)
And what I would like to have :
Array
(
[avignon] => 2
[marseille] => 1
)
I tried with array_count_values, but it dont seems to be the good way.
Any idea?
You could just go through it manually:
$result = array();
foreach($input as $item)
{
$result[$item['ville']]++;
}
or, slightly nicer perhaps,
$result = array();
foreach($input as $item)
{
$city = $item['ville'];
if(!array_key_exists($city, $result)) {
$result[$city] = 1;
} else {
$result[$city]++;
}
}
Alternatively, you could do some array_map magic to first get an array with all the cities, and then use array_count_values as you planned:
$cities = array_count_values( array_map( function($a) { return $a['ville']; } ) );
Note, I haven't tested this last solution, I personally think the first one expresses the intention better. If you would like to use this one because it is shorter (i.e. less readable) I'll leave it to you to debug and comment it
You can use array_reduce():
$data = Array
(
0 => Array
(
'id' => 671,
'title' => 'BIEND',
'img' => '',
'ville' => 'marseille'
)
,
1 => Array
(
'id' => 670,
'title' => 'BIENC',
'img' => '',
'ville' => 'avignon'
)
,
2 => Array
(
'id' => 669,
'title' => 'BIENB',
'img' => '',
'ville' => 'avignon'
)
);
$result = array_reduce($data, function(&$cur, $x)
{
$cur[$x['ville']] = isset($cur[$x['ville']])?$cur[$x['ville']]+1:1;
return $cur;
}, []);
$my_array = array(...);
$result = array();
foreach ($my_array as $arr) {
$key = $arr['ville'];
if (! array_key_exists($key, $result){
$result[$key] = 1;
continue;
}
$result[$key] += 1;
}
I would write something like this. Array and subArray should be renamed according to their content.
$villes = array();
foreach($yourArray as $subArray) {
if(!in_array($subArray['ville'], $villes)) {
$villes[$subArray['ville']] = 1;
} else {
$villes[$subArray['ville']]++;
}
}
var_dump($villes);

PHP arrays. There must be a simpler method to do this

I have this array in php returned from db
Array
(
[inv_templates] => Array
(
[0] => Array
(
[inven_subgroup_template_id] => 1
[inven_group] => Wires
[inven_subgroup] => CopperWires
[inven_template_id] => 1
[inven_template_name] => CopperWires6G
[constrained] => 0
[value_constraints] =>
[accept_range] => 2 - 16
[information] => Measured Manual
)
[1] => Array
(
[inven_subgroup_template_id] => 1
[inven_group] => Wires
[inven_subgroup] => CopperWires
[inven_template_id] => 2
[inven_template_name] => CopperWires2G
[constrained] => 0
[value_constraints] =>
[accept_range] => 1 - 7
[information] => Measured by Automated Calipers
)
)
)
I need to output this kind of multidimensional stuff
Array
(
[Wires] => Array
(
[inv_group_name] => Wires
[inv_subgroups] => Array
(
[CopperWires] => Array
(
[inv_subgroup_id] => 1
[inv_subgroup_name] => CopperWires
[inv_templates] => Array
(
[CopperWires6G] => Array
(
[inv_name] => CopperWires6G
[inv_id] => 1
)
[CopperWires2G] => Array
(
[inv_name] => CopperWires2G
[inv_id] => 2
)
)
)
)
)
)
I currently do this stuff
foreach ($data['inv_templates'] as $key => $value) {
$processeddata[$value['inven_group']]['inv_group_name'] = $value['inven_group'];
$processeddata[$value['inven_group']]['inv_subgroups'][$value['inven_subgroup']]['inv_subgroup_id'] = $value['inven_subgroup_template_id'];
$processeddata[$value['inven_group']]['inv_subgroups'][$value['inven_subgroup']]['inv_subgroup_name'] = $value['inven_subgroup'];
$processeddata[$value['inven_group']]['inv_subgroups'][$value['inven_subgroup']]['inv_templates'][$value['inven_template_name']]['inv_name'] = $value['inven_template_name'];
$processeddata[$value['inven_group']]['inv_subgroups'][$value['inven_subgroup']]['inv_templates'][$value['inven_template_name']]['inv_id'] = $value['inven_template_id'];
}
return $processeddata;
EDIT : A var_export
array (
'inv_templates' =>
array (
0 =>
array (
'inven_subgroup_template_id' => '1',
'inven_group' => 'Wires',
'inven_subgroup' => 'CopperWires',
'inven_template_id' => '1',
'inven_template_name' => 'CopperWires6G',
'constrained' => '0',
'value_constraints' => '',
'accept_range' => '2 - 16',
'information' => 'Measured Manual',
),
1 =>
array (
'inven_subgroup_template_id' => '1',
'inven_group' => 'Wires',
'inven_subgroup' => 'CopperWires',
'inven_template_id' => '2',
'inven_template_name' => 'CopperWires6G',
'constrained' => '0',
'value_constraints' => '',
'accept_range' => '1 - 7',
'information' => 'Measured by Automated Calipers',
),
),
)
The foreach is almost unreadable. There must be a simpler way
$processeddata = array();
foreach($data['inv_templates'] as $key => $value) {
$group = $value['inven_group'];
$processeddata[$group]['inv_group_name'] = $group;
$subgroup = &$processeddata[$group]['inv_subgroups'][$value['inven_subgroup']];
$subgroup['inv_subgroup_id'] = $value['inven_subgroup_template_id'];
$subgroup['inv_subgroup_name'] = $value['inven_subgroup'];
$template = $value['inven_template_name'];
$subgroup['inv_templates'][$template]['inv_name'] = $template;
$subgroup['inv_templates'][$template]['inv_id'] = $value['inven_template_id'];
}
return $processeddata;
Untested code. This structures the array in a multidimensional way, and then uses array_merge_recursive to merge them with the already processed data.
if (!isset($processeddata[$value['inven_group']]))
$processeddata[$value['inven_group']] = array();
$processeddata[$value['inven_group']] = array_merge_recursive(
$processeddata[$value['inven_group']],
array(
'inv_group_name' => $value['inven_group'],
'inv_subgroups' => array(
$value['inven_subgroup'] => array(
'inv_subgroup_id' => $value['inven_subgroup_template_id'],
'inv_subgroup_name' => $value['inven_subgroup'],
'inv_templates' => array(
$value['inven_template_name'] => array(
'inv_name' => $value['inven_template_name'],
'inv_id' => $value['inven_template_id'],
),
),
),
),
)
);
I find this format usually works for me. You could do it more efficient, I've just never cared :D
I started traversing at $yourArray['inv_templates'] though.
function groupToStructure(array $rows, array $keys) {
$tree = array();
$keys = array_reverse($keys);
foreach ($rows as $row) {
$subTree = array($row);
foreach ($keys as $key) {
$subTree = array($row[$key] => $subTree);
}
$tree = array_merge_recursive($tree, $subTree);
}
return $tree;
}
print_r(groupToStructure($rows, array('inven_group', 'inven_subgroup', 'inven_template_name')));

Categories