Reverse array elements with specific value - php

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]

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);
}

Add key/value pair in between two pairs in an array

I have been looking and thinking, but can't come up with a viable solution to this problem.
I have an array with sequencial numerical keys
Example:
Array
(
[0] => value 0
[1] => value 1
[2] => value 2
[3] => value 3
)
I need to add a new key/value pair in between two specific keys in my array.
Example:
I need to add [a] => value a between keys 1 and 2 like
Array
(
[0] => value 0
[1] => value 1
[a] => value a
[2] => value 2
[3] => value 3
)
What I already though of doing, but seems the long way around
slicing my array in two, add my key/value pair to the back of slice one, and recombine my 2 slices into a single array
somehow advancing each key by one after key 1 modifying my new key/value pair to [2] => value a, the add it to the back of the array, and then resort my array
Any suggestions to a quick clean way to achieve this
Dont know why you will do it ...
$array = array(0=>0,1=>1,2=>2,3=>3);
$add = array('a'=>'a');
$before_key = 2;
$new_array = array();
foreach($array as $key=>$val) {
if($key===$before_key) {
$new_array[key($add)] = $add[key($add)];
}
$new_array[$key] = $val;
}
$array = $new_array;
var_dump($array);
I assume that the original array can be associative...
$ar = array
(
'0' => 'value 0',
'1' => 'value 1',
'2' => 'value 2',
'3' => 'value 3',
);
var_dump(insertAfter($ar, '1', array('a' => 'a')));
function insertAfter($arr, $key, $piece)
{
$keys = array_keys($arr);
$index = array_search($key, $keys);
if ($index !== false)
$ar = array_merge(
array_slice($arr, 0, $index + 1, true),
$piece,
array_slice($arr, $index + 1, null, true));
return $ar;
}
Result:
array(5) {
[0]=>
string(7) "value 0"
[1]=>
string(7) "value 1"
["a"]=>
string(1) "a"
[2]=>
string(7) "value 2"
[3]=>
string(7) "value 3"
}
ps: fixed for the keys, but if there is no need in keys preservation then
function insertAfter($arr, $key, $piece)
{
$before = array();
$keys = array_keys($arr);
$index = array_search($key, $keys);
if ($index !== false)
$before = array_splice($arr, 0, $index + 1, $piece);
return array_merge($before, $arr);
}
Here is my pseudocode of my approach (this is written in python but the concept is still there)
for key, item in enumerate(array):
if key == 2:
thirdKey = array[key]
array[1] = a
if key == 3:
fourthKey = array[key]
array[2] = thirdKey
if key == 4:
array[3] = fourthKey
Kind of a long approach but I hope it helps :)

Cast all digital values in array as integer-type, otherwise leave non-digital values as strings

Given an array, how do I convert array starting at key [1] from type string to type int?
Array
(
[0] => "id"
[1] => "6086220176"
[2] => "6542925762"
[3] => "6623113406"
[4] => "6702782948"
)
I've checked out related question how to convert array values from string to int? already, but I would like to skip the first key "id" int he conversion, and not all keys in array!
array_walk($array, function (&$value) {
if (ctype_digit($value)) {
$value = (int) $value;
}
});
var_export($array);
Output:
array (
0 => 'id',
1 => 6086220176,
2 => 6542925762,
3 => 6623113406,
4 => 6702782948,
)
$arr = array_merge(array($arr[0]),array_map('intval', array_slice($arr, 1)));
Output:
array(5) {
[0]=>
string(2) "id"
[1]=>
int(2147483647)
[2]=>
int(2147483647)
[3]=>
int(2147483647)
[4]=>
int(2147483647)
}
Demo.
$array = array($array[0]) + array_map('intval', $array);
(if you want to avoid a foreach loop)
php is loosely typed, you don't need to type cast it. It will do it for you. But if you want to explicitly do this, you can do like this:
$c = count($array)-1;
for ($n=1;$n<$c;$n++) {
$array[$n] = (int) $array[$n];
}
foreach($array as $key => $val){
if($key !== 0){
$array[$key] = (int) $val;
}
}
or
foreach($array as $key => $val){
if(is_numeric($val)){
$array[$key] = (int) $val;
}
}
If all you values are int :
<?php
$arr = array(
[0] => "id"
[1] => "6086220176"
[2] => "6542925762"
[3] => "6623113406"
[4] => "6702782948"
);
$arr = array_map(function($var) {
// Your 'id' is not an int and will not be converted.
return is_numeric($var) ? (int)$var : $var;
}, $arr);
foreach($array as $k => $v){
if($k == 0) continue;
$array[$k] = is_int($v) ? intval($v) : $v; // if it's not convertible to int it keeps the value
}
or if you have non-numeric indexes
$skipped = false;
foreach($array as $k => $v){
if($skipped === false){
$skipped = true;
continue;
}
$array[$k] = is_int($v) ? intval($v) : $v;
}
Another technique not yet mentioned on this page is to encode the array as a json string with the JSON_NUMERIC_CHECK flag so that numeric values are appropriately cast as integers or floats. Then decode the generated string back to an array.
This approach does not require the developer to know in advance the key/index of the value nor require a conditional check on each value to see if the value is numeric. In simple terms, it is highly portable as a general-use strategy.
This technique conveniently accommodates arrays with more than one level.
Code: (Demo)
$array = [
"id",
"6086220176",
"6542925762",
"6623113406",
"6702782948",
['333', [['444']]]
];
var_export(
json_decode(
json_encode(
$array,
JSON_NUMERIC_CHECK
),
true
)
);
Output:
array (
0 => 'id',
1 => 6086220176,
2 => 6542925762,
3 => 6623113406,
4 => 6702782948,
5 =>
array (
0 => 333,
1 =>
array (
0 =>
array (
0 => 444,
),
),
),
)
It's not clever to do this but this could probably works:
$narray = array();
foreach($array as $k => $v){
$narray[$k+1] = $v;
}
$array = $narray;
$array is your array you want to start with 1.

Making values unique in multidimensional array

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),
)));

How do I flatten an associative array into an array with only values in PHP?

I have an array that has keys and values. For eg:
Array (
[name] => aalaap
[age] => 29
[location] => mumbai
)
I want to convert the keys from this into values, but I want the values to apear right after the keys. For eg:
Array (
[0] => name
[1] => aalaap
[2] => age
[3] => 29
[4] => location
[5] => mumbai
)
I can easily write an iteration function that will do this... for eg:
array_flatten($arr) {
foreach ($arr as $arrkey => $arrval) {
$arr_new[] = $arrkey;
$arr_new[] = $arrval;
}
return $arr_new;
}
...but I'm trying to find out if there's any way this can be accomplished using array_combine, array_keys, array_values and/or array_merge, preferably in one, so i don't need to use a custom function.
Is there?
Your own solution is probably the cleanest solution, so converting it to a "one-liner":
$array = array('name' => 'aalaap','age' => 29, 'location' => 'mumbai');
$answer = array();
array_walk($array, create_function('$val,$key', 'global $answer; $answer[]=$key; $answer[]=$val;'));
var_dump($answer);
This avoids unnecessary and expensive array copies or sorting.
Alternatively, lose the global:
array_walk($array, create_function('$val,$key,$result', '$result[]=$key; $result[]=$val;'), &$answer);
I don't think this is possible - with the built-in functions you'll end up with all the keys then all the values:
$a = array('a' => 'A', 'b' => 'B', 'c' => 'C');
$a = array_merge(array_keys($a), array_values($a));
print_r($a);
You're going to have to use a loop like this:
$b = array();
foreach ($a as $key => $value)
{
$b[] = $key;
$b[] = $value;
}
PHP 5.3+ version of Just Jules' answer, and a bit more readable:
array_walk($array, function($val, $key) use (&$answer) {
$answer[] = $key;
$answer[] = $val;
});
It is possible, but I don't think it is more readable or any faster. It would work with a less-known feature of PHP - the array addition:
$array = array('name' => 'aalaap', 'age' => 29, 'location' => 'mumbai');
# Separate keys and values into distinct arrays
$keys = array_keys($array);
$values = array_values($array);
# Generate 2 new array containing indexes for the 2 arrays which contain
# only odd/even numbers:
$keysKeys = range(0, count($keys) * 2 - 1, 2);
$valuesKeys = range(1, count($keys) * 2, 2);
# Combine the keys with the values and add the results:
$array = array_combine($keysKeys, $keys) + array_combine($valuesKeys, $values);
# Sort the resulting array, otherwise the numbering will be broken
# (1,3,5,2,4,6)
ksort($array);
# Result:
var_dump($array);
array(6) {
[0]=>
string(4) "name"
[1]=>
string(6) "aalaap"
[2]=>
string(3) "age"
[3]=>
int(29)
[4]=>
string(8) "location"
[5]=>
string(6) "mumbai"
}
Could use an array_reduce to get close.
array_reduce(array_keys($arr), function($carry, $key)use($arr){
$carry[] = $key;
$carry[] = $arr[$key];
return $carry;
}, array());

Categories