Merge keys of an array based on values - php

I want to merge the keys of array based on values. This is my array.
Array
(
[1] => 1
[2] => 1
[3] => 1
[4] => 2
[5] => 0
[6] => 2
[7] => 2
)
I want output as
Array
(
[1,2,3] => 1
[4,6,7] => 2
[5] => 0
)
I have been brain storming entire day but couldn't find a solution. Any hint would be much appreciated.
WHAT I HAVE TRIED:
for($i=2;$i<=count($new);$i++){
if ($new[$i-1][1]==$new[$i][1]){
$same .= $new[$i-1][0].$new[$i][0];
}
}
echo $same;
But I am stucked. I am comparing the keys one by one but it's very complicated. I don't need the code. I only need the hint or logic. Anyone kind enough?

<?php
$old_arr = ["1"=>1,"2"=>1,"3"=>1,"4"=>2,"5"=>0,"6"=>2,"7"=>2];
$tmp = array();
foreach($old_arr as $key=>$value)
{
if(in_array($value, $tmp)){
$index = array_search($value, $tmp);
unset($tmp[$index]);
$tmp[$index.",".$key] = $value;
}else{
$tmp[$key] = $value;
}
}
ksort($tmp);
echo "<pre>";
print_r($tmp);
echo "</pre>";
?>
https://eval.in/529314

You can loop through array elements and create a new array with new structure. Please check the below code it may help you
$old_array = array(1=> 1,2 => 1,
3=> 1,
4 => 2,
5 => 0,
6 => 2,
7 => 2
);
$new_array = array();
foreach($old_array as $key => $value)
{
if(in_array($value,$new_array))
{
$key_new = array_search($value, $new_array);//to get the key of element
unset($new_array[$key_new]); //remove the element
$key_new = $key_new.','.$key; //updating the key
$new_array[$key_new] = $value; //inserting new element to the key
}
else
{
$new_array[$key] = $value;
}
}
print_r($new_array);

$arr = array(1 => 1, 2 => 1, 3 => 1, 4 => 2, 5 => 0, 6 => 2, 7 => 2);
$tmp = array();
foreach ($arr as $key => $val)
$tmp[$val][] = $key;
$new = array();
foreach ($tmp as $key => $val)
$new[implode(',', $val)] = $key;
First loop the original array through, creating a temporary array, where your original values are keys and values are the original keys as an array.
Then loop the temporary array, creating the new array, where the temporary array's values are imploded as keys.

There's no way to have an array of keys to a single value, but the other way around:
function flipWithKeyArray($arr){
$result = array();
foreach($arr as $key => $val){
if(!isset($result[$val]))
$result[$val] = array();
$result[$val][] = $key;
}
return $result;
}
This will flip your array and declare one array per value of your old array and then push the keys with the same value into each list.
For an array like this:
array(1=>1, 2=>1, 3=>1, 4=>2, 5=>2, 6=>2)
The result will look like this:
array(1=>array(1,2,3), 2=>array(4,5,6))
Hope it fits your need.

Related

How can I sort values from an existing array by data type?

I try to determine the data type of each array value from an existing array using foreach() and var_dump().
Let's say I have this array: example:
$arr = ['this','is', 1, 'array', 'for', 1, 'example'];
Now I have to take each value of this field and determine its data type.
I try this:
$str = array();
$int = array();
foreach($arr as $k => $val) {
if(var_dump($arr[$k]) == 'string'){
$str[] = $arr[$k];
} else {
$int[] = $arr[$k];
}
}
In other words, I try to sort the values from an existing array by data type and create a new array with only 'string' values and a second new array with only 'int' values. But it seems that my 'if' condition isn't working properly. How else could I solve this please? Thank you.
You need to use gettype to get the type of a value, not var_dump:
foreach($arr as $k => $val) {
if(gettype($arr[$k]) == 'string'){
$str[] = $arr[$k];
} else {
$int[] = $arr[$k];
}
}
Output:
Array
(
[0] => this
[1] => is
[2] => array
[3] => for
[4] => example
)
Array
(
[0] => 1
[1] => 1
)
Demo on 3v4l.org
Use gettype
$data = array('this','is', 1, 'array', 'for', 1, 'example');
foreach ($data as $value) {
echo gettype($value), "\n";
}

Populate a previously created associative array, with values

Trying to populate a previously created associative array, with values where values are randomly created. I cannot spot what I am doing wrong.
<?php
$value_min = 1;
$value_max = 3;
$my_array = array (
"dice_1" => null,
"dice_2" => null,
"dice_3" => null
);
foreach(range($value_min, $value_max) as $key => $value) {
$my_array[] = random_int($value_min, $value_max);
};
print_r($my_array);
Outcome:
Array
(
[dice_1] =>
[dice_2] =>
[dice_3] =>
[0] => 2
[1] => 2
[2] => 3
)
Expected outcome
(
[dice_1] => 2
[dice_2] => 2
[dice_3] => 3
)
Note: value can of course diff since they are created with random numbers
just change the foreach
foreach($my_array as $key => $value) {
$my_array[$key] = random_int($value_min, $value_max);
};
Here you can do something like this,
$t = range($value_min, $value_max);
shuffle($t);
$temp = array_combine(array_keys($my_array), $t);
I am fetching keys of $my_array and shuffled range array.
Then combining them as keys as first argument and shuffled range array as second argument.
Demo.
EDIT
In that case you can traverse my_array,
foreach($my_array as $key => &$value) { // & to save data directly to its address
$value = random_int($value_min, $value_max);
};
Demo.
$value_min = 1;
$value_max = 3;
$my_array = array (
"dice_1" => null,
"dice_2" => null,
"dice_3" => null
);
$i=1;
foreach(range($value_min, $value_max) as $key => $value) {
$my_array["dice_".$i] = random_int($value_min, $value_max);
$i++;
};
print_r($my_array);
DEMO

Split flat array into grouped subarrays containing values from consecutive key in the input array

I have an array from array_diff function and it looks like below:
Array
(
[0] => world
[1] => is
[2] => a
[3] => wonderfull
[5] => in
[6] => our
)
As you can see, we have a gap between the keys #3 and #5 (i.e. there is no key #4).
How can I split that array into 2 parts, or maybe more if there are more gaps?
The expected output would be:
Array
(
[0] => Array
(
[0] => world
[1] => is
[2] => a
[3] => wonderfull
)
[1] => Array
(
[0] => in
[1] => our
)
)
You can use old_key,new_key concept to check that there difference is 1 or not? if not then create new index inside you result array otherwise add the values on same index:-
<?php
$arr = Array(0 => 'world',1 => 'is',2 => 'a',3 => 'wonderfull',5 => 'in',6 => 'our');
$new_array = [];
$old_key = -1;
$i = 0;
foreach($arr as $key=>$val){
if(($key-$old_key) ==1){
$new_array[$i][] = $val;
$old_key = $key;
}
if(($key-$old_key) >1){
$i++;
$new_array[$i][] = $val;
$old_key = $key;
}
}
print_r($new_array);
https://3v4l.org/Yl9rp
You can make use of the array internal pointer to traverse the array.
<?php
$arr = Array(0=>"world",1=>"is",2=>"a",3=>"wonderfull",5=>"in",6=>"our");
print_r($arr);
$result = Array();
$lastkey;
while($word = current($arr))
{
$key = key($arr);
if(isset($lastkey) && $key == $lastkey + 1)
{
$result[count($result) - 1][] = $word;
}
else
{
$result[] = Array($word);
}
$lastkey = $key;
next($arr);
}
print_r($result);
?>
This task is a perfect candidate for a reference variable. You unconditionally push values into a designated "bucket" -- in this case a subarray. You only conditionally change where that bucket is in the output array.
There are two important checks to make when determining if a new incremented key should be generated:
if it is not the first iteration and
the current key minus (the previous key + 1) does not equal 0.
Code: (Demo)
$nextKey = null;
$result = [];
foreach ($array as $key => $val) {
if ($nextKey === null || $key !== $nextKey) {
unset($ref);
$result[] = &$ref;
}
$ref[] = $val;
$nextKey = $key + 1;
}
var_export($result);
This solution generates an indexed array starting from zero with my sample input and uses only one if block. In contrast, AliveToDie's solution generates a numerically keyed array starting from 1 and uses two condition blocks containing redundant lines of code.

Loop a 2d array and merge row data if encountered row key is found in previously stored subarray

I want to consolidate an associative array of indexed arrays by merging rows which have an associative key that is in another row's values.
Consider this sample input:
$array = [
44259 => [50007, 50009, 46372],
50007 => [50008],
50009 => [50010],
66666 => ['no', 'other', 'links'],
46372 => [46418, 46419, 46421],
46421 => [146880]
];
Because the values in the 44259-keyed row (50007, 50009, and 46372) exist as keys in the original array, all of the values from those values should be pushed into the 44259-keyed row.
Continuing the same logic, after the 46372-keyed rows have been added to 44259-keyed row, now the 46421-keyed row values should be pushed into the growing 44259-keyed row.
Desired result:
$array = [
44259 => [
50007, // original
50009, // original
46372, // original
50008, // from 50007
50010, // from 50009
50018, // from 46372
46419, // from 46372
46421, // from 46372
146880, // from 46372 -> 46421
66666 => [
'no',
'other',
'links'
]
];
You see, this is somewhat of a recursive task.
I tried this already:
foreach ($array as $cid => $pid) {
foreach ($pid as $pip) {
if (isset($array[$pipp])) {
foreach ($array[$pipp] as $pip) {
$array[$cid][] = $pip;
unset($array[$pipp]);
}
}
}
}
But it's not properly collecting the 46372 row's data for the 44259 row.
You could get the first key using array_keys() and reset(). Then you could add values of all array to this key:
$array = [];
$array[44259] = [50007, 50009, 46372];
$array[50007] = [50008];
$array[50009] = [50010];
$array[46372] = [46418, 46419, 46421];
$array[46421] = [146880];
$out = [];
$keys = array_keys($array);
$first_key = reset($keys); // $first_key = 44259
foreach ($array as $k => $items) {
foreach ($items as $val) {
$out[$first_key][] = $val;
}
}
print_r($out);
Outputs:
Array
(
[44259] => Array
(
[0] => 50007
[1] => 50009
[2] => 46372
[3] => 50008
[4] => 50010
[5] => 46418
[6] => 46419
[7] => 46421
[8] => 146880
)
)
You coukd try just merging
$result =array_merge($array[44259],$array[50007] ,$array[50009] ,
$array[46372], $array[46421] );
$res = array();
$res[44259] = array();
foreach($array as $pid)
$res[44259] = array_merge($res[44259], $pid);
print_r($res);
?>
Ouput
Array
(
[44259] => Array
(
[0] => 50007
[1] => 50009
[2] => 46372
[3] => 50008
[4] => 50010
[5] => 46418
[6] => 46419
[7] => 46421
[8] => 146880
)
)
This is probably one way of doing it. Create another array and push all the variables in the new array.
$result=[];
foreach ($array as $v1) {
foreach ($v1 as $v2) {
array_push($result,$v2);
}
}
Have you tried array_merge?
$mergedArray = [];
foreach ($array as $subArray) {
$mergedArray = array_merge ($mergedArray, $subArray);
}
If that doesn't work, then you could probably use array_map to run a function on each sub array element to check if it is in the merged array before adding it.
$mergedArray = [];
foreach ($array as $subArray) {
array_map(function($elm) {
if (!in_array($elm, $mergedArray)) {
$mergedArray[] = $elm;
}, $subArray);
}
You were very close, but you need to allow your script to restart the full array loop after consolidating data.
I recommend a do{}while() loop so that the inner processing can be repeated until there are no qualifying/moveable rows.
A nested loop is then used to search for first level keys that match any of the row values. Make the rows modifiable by reference with & -- this will ensure that the data manipulations are upon the original array and not merely a copy of the original array.
When there is a matching key, push the entire found row into the parent row, then remove the now-empty row from the original array, then toggle the flag indicating that another loop is required, then break
Code: (Demo)
do {
$changes = false;
foreach ($array as $k => &$row) {
foreach ($row as $v) {
if (isset($array[$v])) {
array_push($array[$k], ...$array[$v]);
unset($array[$v]);
$changes = true;
}
}
}
} while($changes);
var_export($array);

need to search for values in each string of an array to construct another array

I have this array:
Array
(
[count] => 12
[6] => CN=G_Information_Services,CN=Users,DC=hccc,DC=campus
[7] => CN=WEBadmin,CN=Users,DC=hccc,DC=campus
[9] => CN=G_ISDept,CN=Users,DC=hccc,DC=campus
[10] => CN=STAFF,CN=Users,DC=hccc,DC=campus
)
and I want to create an array of values that consist of the value between the first CN= and , of each array value below.
I probably will have to loop thru the array above, do a regex search for the first occurrence of cn and the value that follows it
I am not sure what I am doing wrong.
I need the final result to be an array that resembles this:
array('G_Information_Services', 'WEBadmin', 'G_ISDept', 'STAFF');
Use preg_match on each of the array values to get only the first corresponding CN value.
$found = array();
foreach ($arr AS $values) {
if (preg_match('/CN=([^,]+),/',$values,$matches))
$found[] = $matches[1];
}
Output
Array
(
[0] => G_Information_Services
[1] => WEBadmin
[2] => G_ISDept
[3] => STAFF
)
Try this (not the most efficient way but it should work):
foreach ($array as $key => $value)
{
if (is_numeric($key))
{
$array[$key] = explode(',', $array[$key]);
$array[$key] = $array[$key][0];
$array[$key] = substr($array[$key], 3);
}
}
This gets the first value of CN= of each element of the array, it also ignores any DC= values.
$arr = array(
'count' => 12,
6 => 'CN=G_Information_Services,CN=Users,DC=hccc,DC=campus',
7 => 'CN=WEBadmin,CN=Users,DC=hccc,DC=campus',
9 => 'CN=G_ISDept,CN=Users,DC=hccc,DC=campus',
10 => 'CN=STAFF,CN=Users,DC=hccc,DC=campus'
);
$newArr = array();
foreach($arr as $key => $value)
{
if($key != 'count')
{
$temp = explode(',', $value);
foreach($temp as $item)
{
if(strpos($item, 'CN=') === 0)
{
$item = substr($item, 3 );
$newArr[] = $item;
break 1;
}
}
}
}
print_r($newArr);

Categories