Making values unique in multidimensional array - php

I have some Problems reducing a multidimensional array into a normal one.
I have an input array like this:
Array
(
[0] => Array (
[0] => 17
[1] => 99
)
[1] => Array (
[0] => 17
[1] => 121
)
[2] => Array (
[0] => 99
[1] => 77
)
[3] => Array (
[0] => 45
[1] => 51
)
[4] => Array (
[0] => 45
[1] => 131
)
So I have a multidimensional array with some overlaps in the values (eg 17,99 and 17,121)
Now I want to have an output like this:
Array
(
[0] => Array (
[0] => 17
[1] => 99
[2] => 121
[3] => 77
)
[2] => Array (
[0] => 45
[1] => 51
[3] => 131
)
I want to save, which articles are the same in my database this way. The output array shpuld still be a multidimesional array, but every number on the second level should be unique in the array.
I'm trying to solve this for more than a week now, but I dont get it to work. I know it should be easy...but anyway - I dont get it :D
This is what i got so far:
$parity_sorted = array();
foreach($arr as $key => $a){
if(count($parity_sorted) > 0){
foreach($parity_sorted as $key2 => $arr_new){
if(in_array($a[0], $arr_new) || in_array($a[1], $arr_new)){
if(!in_array($a[0], $arr_new)){array_push($parity_sorted[$key2], $a[0]);}
if(!in_array($a[1], $arr_new)){array_push($parity_sorted[$key2], $a[1]);}
} else {
array_push($parity_sorted, array($a[0],$a[1]));
}
}
} else {
array_push($parity_sorted, array($a[0],$a[1]));
}
}
Did you maybe already solve problem like this or is there a much easier way? Maybe I just think too complicated (It's not my first try, but this code was the last try)
Any help would be appreciated. Thanks a lot

Here is my revised code given your comment and a DEMO of it working as expected. ( http://codepad.org/CiukXctS )
<?php
$tmp = array();
foreach($array as $value)
{
// just for claraty, let's set the variables
$val1 = $value[0];
$val2 = $value[1];
$found = false;
foreach($tmp as &$v)
{
// check all existing tmp for one that matches
if(in_array($val1, $v) OR in_array($val2, $v))
{
// this one found a match, add and stop
$v[] = $val1;
$v[] = $val2;
// set the flag
$found = true;
break;
}
}
unset($v);
// check if this set was found
if( ! $found)
{
// this variable is new, set both
$tmp[] = array(
$val1,
$val2,
);
}
}
// go trough it all again to ensure uniqueness
$array = array();
foreach($tmp as $value)
{
$array[] = array_unique($value); // this will eliminate the duplicates from $val2
}
ORIGIN ANSWER
The question is badly asked, but I'll attempt to answer what I believe the question is.
You want to gather all the pairs of arrays that have the same first value in the pair correct?
$tmp = array();
for($array as $value)
{
// just for claraty, let's set the variables
$val1 = $value[0];
$val2 = $value[1];
if(isset($tmp[$val1])) // we already found it
{
$tmp[$val1][] = $val2; // only set the second one
}
else
{
// this variable is new, set both
$tmp[$val1] = array(
$val1,
$val2,
);
}
}
// go trough it all again to change the index to being 0-1-2-3-4....
$array = array();
foreach($tmp as $value)
{
$array[] = array_unique($value); // this will eliminate the duplicates from $val2
}

Here is solution for common task.
$data = array(array(17,99), array(17,121), array(99,77), array(45,51), array(45,131));
$result = array();
foreach ($data as $innner_array) {
$intersect_array = array();
foreach ($result as $key => $result_inner_array) {
$intersect_array = array_intersect($innner_array, $result_inner_array);
}
if (empty($intersect_array)) {
$result[] = $innner_array;
} else {
$result[$key] = array_unique(array_merge($innner_array, $result_inner_array));
}
}
var_dump($result);

Try:
$arr = array(array(17,99),
array(17,121),
array(99,77),
array(45, 51),
array(45, 131)
);
foreach($arr as $v)
foreach($v as $m)
$new_arr[] = $m;
$array = array_chunk(array_unique($new_arr), 4);
var_dump($array);
Demo
It uses array_unique and array_chunk.
Output:
array(2) { [0]=>array(4) { [0]=> int(17) [1]=>int(99)
[2]=>int(121) [3]=> int(77) }
[1]=> array(3) { [0]=> int(45) [1]=>int(51)
[2]=>int(131) }
}

I think I get your problem. Let me have a crack at it.
$firstElems = array();
$secondElems = array();
foreach ( $arr as $v ) {
$firstElems[ $v[0] ] = array( $v[0] );
}
foreach ( $arr as $v ) {
$secondElems[ $v[1] ] = $v[0];
}
foreach ( $arr as $v ) {
if ( isset( $secondElems[ $v[0] ] ) ) {
array_push( $firstElems[ $secondElems[ $v[0] ] ], $v[1] );
}
else {
array_push( $firstElems[ $v[0] ], $v[1] );
}
}
foreach ( $firstElems as $k => $v ) {
if ( isset( $secondElems[ $k ] ) ) {
unset( $firstElems[ $k ] );
}
}
Output:
Array
(
[17] => Array
(
[0] => 17
[1] => 99
[2] => 121
[3] => 77
)
[45] => Array
(
[0] => 45
[1] => 51
[2] => 131
)
)

(Code examples: http://codepad.org/rJNNq5Vd)
I truly believe I understand you and if this is the case here is what you're looking for:
function arrangeArray($array) {
$newArray = array(array_shift($array));
for ($x = 0; $x < count($newArray); $x++) {
if (!is_array($newArray[$x])) {
unset($newArray[$x]);
return $newArray;
}
for ($i = 0; $i < count($newArray[$x]); $i++) {
foreach ($array as $key => $inArray) {
if (in_array($newArray[$x][$i], $inArray)) {
$newArray[$x] = array_unique(array_merge($newArray[$x], $inArray));
unset($array[$key]);
}
}
}
$newArray[] = array_shift($array);
}
}
Which will return:
array(2) {
[0]=>
array(4) {
[0]=>
int(17)
[1]=>
int(99)
[2]=>
int(121)
[4]=>
int(77)
}
[1]=>
array(3) {
[0]=>
int(45)
[1]=>
int(51)
[3]=>
int(131)
}
}
For:
var_dump(arrangeArray(array(
array(17,99),
array(17,121),
array(99,77),
array(45, 51),
array(45, 131),
)));
And:
array(1) {
[0]=>
array(6) {
[0]=>
int(17)
[1]=>
int(99)
[2]=>
int(121)
[3]=>
int(45)
[4]=>
int(77)
[6]=>
int(51)
}
}
For:
var_dump(arrangeArray(array(
array(17,99),
array(17,121),
array(99,77),
array(45, 51),
array(45, 17),
)));

Related

How to get hyrarchy from key elements and create new elements based on that - PHP

I have a very big array, I will try to explain the issue in small examples:
Input:
Array (
[alert:accountDisabled:heading] => XYZ
[alert:accountDisabled:message] => XYZ
[alert:accountExpired:heading] => XYZ
[alert:accountExpired:message] => XYZ
[alert:errorResponse:heading] => XYZ
[button:back] => XYZ
)
What I need to get is:
array() {
["alert"]=> array(7) {
["accountDisabled"]=> array(2) {
["heading"]=> string(3) "XYZ"
["message"]=> string(3) "XYZ" }
["accountExpired"]=> array(2) {
["heading"]=> string(3) "XYZ"
["message"]=> string(3) "XYZ" }
["clientError"]=> array(2) {
["heading"]=> string(3) "XYZ"
["message"]=> string(3) "XYZ" }
["errorResponse"]=> array(1) {
["heading"]=> string(3) "XYZ" }
}
["button"]=> array(1) {
["back"]=> string(3) "XYZ"
}
As I said this is a very small example, but the point is to get hierarchy from keys from array number one, hierarchy is divided by this character in key :
I checked for those questions that look similar to this one but they are not helpful lat all
How to access and manipulate multi-dimensional array by key names / path?
Using a string path to set nested array data
SO please read carefully the description of my issue.
I tried to use it for each loop, and I succeed to divide elements from the key, for one element, but I'm not sure where I need to store those hierarchy values for the next elements, any ideas?
$input = [
'alert:accountDisabled:heading' => 'XYZ_1',
'alert:accountDisabled:message' => 'XYZ_2',
'alert:accountExpired:heading' => 'XYZ_3',
'alert:accountExpired:message' => 'XYZ_4',
'alert:errorResponse:heading' => 'XYZ_5',
'button:back' => 'XYZ_6'
];
$results = [];
foreach ($input as $key => $value) {
$arr = explode(':', $key);
$result = $value;
for ($i = count($arr) - 1; $i >= 0; $i--) {
$result = [ $arr[$i] => $result ];
}
$results[] = $result;
}
$result = array_merge_recursive(...$results);
print_r($result);
Output:
Array
(
[alert] => Array
(
[accountDisabled] => Array
(
[heading] => XYZ_1
[message] => XYZ_2
)
[accountExpired] => Array
(
[heading] => XYZ_3
[message] => XYZ_4
)
[errorResponse] => Array
(
[heading] => XYZ_5
)
)
[button] => Array
(
[back] => XYZ_6
)
)
Based on Lukas.j answer, you can use this function:
function parsePath($array, $separator = ':'){
$result = [];
foreach($array as $key => $value){
if(strpos($key, $separator) !== FALSE){
$keys = explode($separator, $key);
$inner_result = $value;
foreach (array_reverse($keys) as $valueAsKey) $inner_result = [$valueAsKey => $inner_result];
$result[] = $inner_result;
}
}
return array_merge_recursive(...$result);
}

Get keys from multidimensional array recursively

I have multidimensional array like this. It is in var_dump() formatting.
array(1) {
[4]=>
array(1) {
[2]=>
array(1) {
[5]=>
array(1) {
[1]=>
array(1) {
[3]=>
array(1) {
[6]=>
array(0) {
}
}
}
}
}
}
}
aka $multiArray and i want to get all keys from it and set them to get array like this.
[0=>4, 1=>2, 2=>5, 3=>1, 4=>3, 5=>6] aka **$keysArray**.
Tried like this.
foreach( new \RecursiveIteratorIterator(
new \RecursiveArrayIterator(**$multiArray**),
\RecursiveIteratorIterator::SELF_FIRST)
as $key => $value) {
**$keysArray[]** = $key;
}
also this.
function array_keys_multi(array $array) {
$keys = [];
foreach ($array as $key => $value) {
$keys[] = $key;
if (is_array($value)) {
$keys = array_merge($keys, $this->array_keys_multi($value));
}
}
return $keys;
}
but both of them returns incorrect data. How can i get all keys?
This seems to work for me:
function array_keys_recursive(array $arr) {
foreach($arr as $key => $value) {
$return[] = $key;
if(is_array($value)) $return = array_merge($return, array_keys_recursive($value));
}
return $return;
}
Basically identical to yours, which also works, by the way.
I used a recursive function:
<?php
$multiArray =
array( 4 =>
array (
2 =>
array (
5 =>
array (
1 =>
array (
3 =>
array (
6 =>
array (
)
)
)
)
)
)
);
$keysArray = array();
$depth = 0;
function newArray($array, &$keysArray) {
foreach ($array as $key => $value) {
$depth++;
array_push($keysArray, $key);
if( is_array($value) && $depth < 10 ) { newArray($value, $keysArray ); }
}
}
newArray($multiArray, $keysArray);
print_r( $keysArray ); // Your expected result
// $keysArray = Array ( [0] => 4 [1] => 2 [2] => 5 [3] => 1 [4] => 3 [5] => 6 )
?>
I used the variable $depth to prevent going loop crazy

Merge two dimensional array in PHP

for a long time can't resolve smth looking like as very simple matter... I want merge a two dimensional arrays.
The example:
$arr1 = {
[532] =
{
[0] = "11"
[1] = "12"
}
[273] =
{
[0] = "99"
}
}
$arr2 = {
[532] =
{
[0] = "11"
[1] = "13"
}
}
And the result of merging should be, a map on common keys, exactly like that array:
$result = {
[532] =
{
[0] =
{
[0] = "11"
[1] = "12"
}
[1] =
{
[0] = "11"
[1] = "13"
}
}
[273]
[0] =
{
[0] = "99"
}
[1] =
{
}
}
I try sometihng like that:
$result = $arr1;
foreach ($arr2 as $key => $value) {
$result[$key] = isset($result[$key]) ? array_merge([$result[$key]], [$value]) : [$value];
}
But it doesnt work if $arr2 is empty :(
For the second array checking, you need to use isset() either array set or not:
Example:
<?php
$arr1 = array('532'=>array('11','12'),'273'=>array('99'));
$arr2 = array('532'=>array('11','13'));
$newArr = array();
foreach ($arr1 as $key => $value) {
if(isset($arr2[$key])){
$newArr[$key][] = $value;
$newArr[$key][] = $arr2[$key];
}
else{
$newArr[$key] = $value;
}
}
echo "<pre>";
print_r($newArr);
?>
Result:
Array
(
[532] => Array
(
[0] => Array
(
[0] => 11
[1] => 12
)
[1] => Array
(
[0] => 11
[1] => 13
)
)
[273] => Array
(
[0] => 99
)
)
Further more, if you want to merge both same index than you can use array_merge() some thing like that:
<?php
$arr1 = array('532'=>array('11','12'),'273'=>array('99'));
$arr2 = array('532'=>array('11','13'));
$newArr = array();
foreach ($arr1 as $key => $value) {
if(isset($arr2[$key])){
$newArr[$key][] = array_merge($value,$arr2[$key]);
}
else{
$newArr[$key] = $value;
}
}
echo "<pre>";
print_r($newArr);
?>
Result:
Array
(
[532] => Array
(
[0] => Array
(
[0] => 11
[1] => 12
[2] => 11
[3] => 13
)
)
[273] => Array
(
[0] => 99
)
)
Note that, ist script, will give you result as you need with unique index.
Second script will give you all values in one single array.
Probably something like this
$arr1 = {
[532] =
{
[0] = "11"
[1] = "12"
}
[273] =
{
[0] = "99"
}
}
$arr2 = {
[532] =
{
[0] = "11"
[1] = "13"
}
}
$newarray = array();
foreach ($arr1 as $key => $value) {
$cu = $arr1[$key];
$newarray[$key][] = $cu;
if(!isset($arr2[$key])) {
$newarray[$key][] = array();
}
else {
$newarray[$key][] = $arr2[$key];
}
}
foreach ($arr2 as $key => $value) {
if(!isset($newarray[$key])) {
$newarray[$key][] = $arr2[$key];
}
}

Reverse array elements with specific value

I have an array like this
$array = array( [0] => 'red1', [1] => 'blue1', [2] => 'red2', [3] => 'red3', [4] => 'blue2' );
A want to reverse order of elements with red value only so it looks like this:
$array = array( [0] => 'red3', [1] => 'blue1', [2] => 'red2', [3] => 'red1', [4] => 'blue2' );
I think a possible solution might be to:
Get all the values from the $array that you are looking for and
store them in an array $found
Reverse the values in $found keeping the keys
Replace the values in $array with the values from $found using
the key
For example:
$array = array(0 => 'red1', 1 => 'blue1', 2 => 'red2', 3 => 'red3', 4 => 'blue2');
// First get all the values with 'red' and store them in an array
$found = preg_grep('/red\d+/', $array);
// Reverse the values, keeping the keys
$found = array_combine(
array_keys($found),
array_reverse(
array_values($found)
)
);
// Then replace the values of $array with values having the same keys in $found
$array = array_replace($array, $found);
var_dump($array);
Will result in:
array(5) {
[0]=>
string(4) "red3"
[1]=>
string(5) "blue1"
[2]=>
string(4) "red2"
[3]=>
string(4) "red1"
[4]=>
string(5) "blue2"
}
You can catch red's quote to a new array and sort them.
<?php
$arr = array(
'red1',
'blue1',
'red2',
'red3',
'blue2'
);
$sortArr = array();
for ($i=0; $i < sizeof($arr); $i++) {
if(strstr($arr[$i], "red")){
$sortArr[] = &$arr[$i];
}
}
?>
I think you can do using searching specific words by strpos and sorting array by ksort (sort associative arrays in ascending order, according to the key)
foreach ($array as $key => $value) {
if(strpos($value,"red") !== false){
($key === 0) ? $index = 3 : (($key === 3) ? $index = 0 : $index = 2);
$temp[$index] = $value;
}
else {
$temp[$key] = $value;
}
}
ksort($temp);
var_dump($temp);
[But It will not work in larger array than this]

Combine pairs to groups [PHP / Arrays]

I have pairs of items in an PHP array. Example:
<?php
$elements = array(
'tiger'=>'lion',
'car'=>'bike',
'lion'=>'zoo',
'truck'=>'plane'
);
?>
Now I want to combine these items so that all items which are connected in any way go to one group. Continuation of the example above:
<?php
$groups = array(
0=>array('tiger', 'lion', 'zoo'),
1=>array('car', 'bike'),
2=>array('truck', 'plane'
);
?>
Is this understandable? How could I achieve this?
I'm looking for a function which does this.
<?php
$elements = array(
'tiger' => 'lion',
'car' => 'bike',
'lion' => 'zoo',
'truck' => 'plane'
);
$groups = array();
foreach ($elements as $key => $val) {
$appended = false;
foreach ($groups as &$group) {
if ($group[0] == $key) {
array_unshift($group, $val);
$appended = true;
break;
}
}
if (!$appended) {
$groups[] = array($val, $key);
}
}
var_dump($groups);
Gives:
array(3) {
[0]=>
array(3) {
[0]=>
string(3) "zoo"
[1]=>
string(4) "lion"
[2]=>
string(5) "tiger"
}
[1]=>
&array(2) {
[0]=>
string(4) "bike"
[1]=>
string(3) "car"
}
[2]=>
array(2) {
[0]=>
string(5) "plane"
[1]=>
string(5) "truck"
}
}
Here's an O(n) solution:
$elements = array(
'tiger' => 'lion',
'car' => 'bike',
'lion' => 'zoo',
'truck' => 'plane'
);
$groups = array();
$sub = array();
$ignore = array();
foreach ( $elements as $key=>$value ) {
if ( isset($ignore[$key]) ) {
continue;
}
$sub = array($key, $value);
if ( isset($elements[$value]) ) {
$ignore[$value] = 1;
$sub[] = $elements[$value];
}
$groups[] = $sub;
}
print_r($groups);
Result:
Array
(
[0] => Array
(
[0] => tiger
[1] => lion
[2] => zoo
)
[1] => Array
(
[0] => car
[1] => bike
)
[2] => Array
(
[0] => truck
[1] => plane
)
)
The idea is simple:
Create a new array to hold your groups
Loop over the item array
Check if the group for the item exists in the group array - if it does not, create it
Put item in group

Categories