I have two arrays
$array1 = ["name1","name2","name3","name4"];
$array2 = ["name2","name1","name3","name4"];
What I would like to know is the position changes between the arrays. In the above example the output will be:
$returnArray = [
"name2"=>"up",
"name1"=>"down",
"name3"=>"same",
"name4"=>"same"
];
up = moved position up
down = moved position down
same = stayed on the same position
What is the quickest way to determine the position changes comparing the two arrays?
This should work for you:
Just loop through all unique values of $array1 and check with array_search()
if the value is at the same position, down or up.
<?php
$array1 = ["name1","name2","name3","name4"];
$array2 = ["name2","name1","name3","name4"];
$result = [];
foreach(array_unique($array1) as $k => $v){
$result[$v] = $k == array_search($v, $array2) ? "same" : ($k < array_search($v, $array2) ? "up": "down");
}
print_r($result);
?>
And in PHP 7 just use the spaceship operator, e.g.
<?php
$array1 = ["name1","name2","name3","name4"];
$array2 = ["name2","name1","name3","name4"];
$arr = ["-1" => "down", "0" => "same", "1" => "up"];
$result = [];
foreach(array_unique($array1) as $k => $v){
$result[$v] = $arr[array_search($v, $array2) <=> $k];
}
print_r($result);
?>
Related
I have two arrays:
$array_one = array('AA','BB','CC');
And:
$replacement_keys = array
(
""=>null,
"BFC"=>'john',
"ASD"=>'sara',
"CSD"=>'garry'
);
So far I've tried
array_combine and to make a loop and try to search for values but can't really find a solution to match the keys of the second array with the values of the first one and replace it.
My goal is to make a final output:
$new_array = array
(
''=>null,
'BB' => 'john',
'AA' => 'sara',
'CC' => 'garry'
);
In other words to find a matching first letter and than replace the key with the value of the first array.
Any and all help will be highly appreciated.
Here is a solution keeping both $replacement_keys and $array_one intact
$tempArray = array_map(function($value){return substr($value,0,1);}, $array_one);
//we will get an array with only the first characters
$new_array = [];
foreach($replacement_keys as $key => $replacement_key) {
$index = array_search(substr($key, 0, 1), $tempArray);
if ($index !== false) {
$new_array[$array_one[$index]] = $replacement_key;
} else {
$new_array[$key] = $replacement_key;
}
}
Here is a link https://3v4l.org/fuHSu
You can approach like this by using foreach with in_array
$a1 = array('AA','BB','CC');
$a2 = array(""=>null,"BFC"=>'john',"ASD"=>'sara',"CSD"=>'garry');
$r = [];
foreach($a2 as $k => $v){
$split = str_split($k)[0];
$split .= $split;
in_array($split, $a1) ? ($r[$split] = $v) : ($r[$k] = $v);
}
Working example :- https://3v4l.org/ffRWY
I want to rank the keys of an associative array in php based upon their values. (top to down as 1, 2, 3....). Keys having same value will have same rank.
Here function getRanks() is meant to return an array containing keys and the ranks (number).
I expect it to return like this (this is sorted value wise in descending)
Array
(
[b] => 1
[a] => 2
[d] => 3
[c] => 3
[e] => 4
)
There is issue in assigning the ranks (values) in the $ranks array which is to be returned.
What am I doing wrong? Do these loops even do something?
Code:
$test = array('a'=> 50, 'b'=>60, 'c'=>20, 'd'=>20, 'e'=>10);
$json = json_encode($test);
print_r(getRanks($json));
function getRanks($json) {
$tmp_arr = json_decode($json, TRUE);
$ranks = array();
uasort($tmp_arr, function($a, $b){
return $a == $b ? 0 : $a > $b ? -1 : 1; //descending
});
$keys = array_keys($tmp_arr); //after sorting
$ranks = array_fill_keys($keys, 0); //copy keys
$ranks[$keys[0]] = 1; //first val => rank 1
//------- WORKS FINE UNTIL HERE ------------------
// need to fix the ranks assignment
for($i=1; $i<count($keys)-1; $i++) {
for($j=$i; $j < count($keys)-1; $j++) {
if($tmp_arr[$keys[$j]] == $tmp_arr[$keys[$j+1]]) {
$rank[$keys[$j]] = $i;
}
}
}
return $ranks;
}
Your approach seems unnecessarily complicated. In my version I kept the json-related copying part of it but finished it off in a simpler way:
function getRanks($json) {
$tmp_arr = json_decode($json, TRUE);
asort($tmp_arr);. // sort ascending
$i=0; $lv=null;$ranks = array();
foreach ($tmp_arr as $k=>$v) {
if ($v>$lv){ $i++; $lv=$v;}
$ranks[$k]=$i;
}
return $ranks;
}
See the demo here: https://rextester.com/LTOA23372
In a slightly modified version you you can also do the ranking in a descending order, see here: https://rextester.com/HESQP10053
I've also tried with another approach.
I think it may not be the good solution because of high memory & CPU time consumption.
For small arrays (in my case) it works fine.
(I've posted because it may be an answer)
It creates array of unique values and fetches ranks accordingly.
$test = array('a'=> 50, 'b'=>60, 'c'=>20, 'd'=>20, 'e'=>10);
$json = json_encode($test);
print_r(getRanks($json));
function getRanks($json) {
$tmp_arr = json_decode($json, TRUE);
arsort($tmp_arr);
$uniq_vals = array_values(array_unique($tmp_arr)); // unique values indexed numerically from 0
foreach ($tmp_arr as $k => $v) {
$tmp_arr[$k] = array_search($v, $uniq_vals) + 1; //as rank will start with 1
}
return $tmp_arr;
}
This is the simple thing that you can do it by using php array function check example given below.
<?php
$fruits = array("d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple");
asort($fruits);
foreach ($fruits as $key => $val) {
echo "$key = $val\n";
}
?>
I have arrays like these :
$array1 = [1,2,3];
$array2 = [3,2,1];
$array3 = [2,1,3];
$array4 = [2,1,3];
$array5 = [1,1,1];
$array6 = [3,3,2];
$array7 = [1,2,1];
$array8 = [8,9,2];
I want to check how array2 until array8 compare to array1. It should give me expected return like this :
$array2 = [3,2,1]; return 'match'
$array3 = [2,1,3]; return 'match'
$array4 = [2,3,1]; return 'match'
$array5 = [1,1,1]; return 'not match'
$array6 = [3,3,2]; return 'not match'
$array7 = [1,2,1]; return 'not match'
$array8 = [8,9,2]; return 'not match'
I tried to compare it using array_diff() but sometimes the result is not like what I expected, especially if on array2 have two same values.
note : array2 until array8 need to always have all 3 values from array1
You just need to sort both arrays before comparing them e.g.
sort($array1);
for ($i = 2; $i <= 8; $i++) {
sort(${"array$i"});
echo "array $i: " . ($array1 == ${"array$i"} ? 'match' : 'no match') . "\n";
}
Output:
array 2: match
array 3: match
array 4: match
array 5: no match
array 6: no match
array 7: no match
array 8: no match
Demo on 3v4l.org
You can use array_unique() and then array_diff() for this task:
$array1 = array_unique($array1);
$array2 = array_unique($array2);
$result = array_diff($array1, $array2);
Description of array_unique():
array_unique ( array $array [, int $sort_flags = SORT_STRING ] ) : array
array_unique — Removes duplicate values from an array
Sorting type flags:
SORT_REGULAR - compare items normally (don't change types)
SORT_NUMERIC - compare items numerically
SORT_STRING - compare items as strings
SORT_LOCALE_STRING - compare items as strings, based on the current locale.
You need to sort the arrays so that indexing will be comparable.
Take a parent array and add all array elements in it.
Loop over the parent array.
sort() children arrays.
Compare there and you will get results.
Code:
<?php
$array1 = [1,2,3];
$array2 = [3,2,1];
$array3 = [2,1,3];
$array4 = [2,1,3];
$array5 = [1,1,1];
$array6 = [3,3,2];
$array7 = [1,2,1];
$array8 = [8,9,2];
$arr['array_1'] = [1,2,3];
$arr['array_2'] = [3,2,1];
$arr['array_3'] = [2,1,3];
$arr['array_4'] = [2,1,3];
$arr['array_5'] = [1,1,1];
$arr['array_6'] = [3,3,2];
$arr['array_7'] = [1,2,1];
$arr['array_8'] = [8,9,2];
$find = [1,2,3];
if (! empty($arr)) {
foreach ($arr as $key => $elem) {
sort($arr[$key]);
if ($arr[$key] == $find) {
echo "<br/>[" . implode(',', $elem) . "]: Match";
}
else {
echo "<br/>[" . implode(',', $elem) . "]: No Match";
}
}
}
Output:
[1,2,3]: Match
[3,2,1]: Match
[2,1,3]: Match
[2,1,3]: Match
[1,1,1]: No Match
[3,3,2]: No Match
[1,2,1]: No Match
[8,9,2]: No Match
Although using array_diff is okay, there's an easier way to compare two arrays you can just use ==
<?php
$array1 = [1,2,3];
$array2 = [3,2,1];
$array3 = [2,1,3];
$array4 = [2,1,3];
$array5 = [1,1,1];
$array6 = [3,3,2];
$array7 = [1,2,1];
$array8 = [8,9,2];
for($i = 2; $i <= 8; ++$i) {
sort(${"array$i"});
echo ${"array$i"} == $array1 ? 'match' : 'not match';
echo PHP_EOL;
}
output:
match
match
match
not match
not match
not match
not match
PHP MANUAL
$a == $b Equality TRUE if $a and $b have the same key/value pairs.
$a === $b Identity TRUE if $a and $b have the same key/value pairs in the same order and of the same types.
The fastest way would be to convert your array to associative one. You can use array_flip function to achieve it. Then you need only to check difference in keys which should be fast using array_diff_key. For example:
$array1 = [1,2,3];
$array2 = [3,2,1];
$array3 = [2,1,3];
$array4 = [2,1,3];
$array5 = [1,1,1];
$array6 = [3,3,2];
$array7 = [1,2,1];
$array8 = [8,9,2];
var_dump(
empty( // if it's empty then the arrays are identical
array_diff_key(array_flip($array1), array_flip($array5))
)
);
But this will only work if you don't care if any array contains duplicate values. If number or order of elements is important then this won't work.
at first need to reduce duplicate data from each array by using php array_unique function
Then make difference two array by using array_diff function
<?php
$firstArray = array_unique($firstArray);
$secondArray = array_unique($secondArray);
$arrayDiff = array_diff($firstArray, $secondArray);
?>
This question already has answers here:
Transpose and flatten two-dimensional indexed array where rows may not be of equal length
(4 answers)
Closed 5 months ago.
There are two arrays , the second array will always be smaller by 1 from first array. The first array contains the numbers and second array contains the mathematical operators.
$arr1 = [210,11,12];
$arr2 = ['-','/'];
the code which i have written is working on this test case only ,but when i increase the number of elements in it. It fails.
$arr1 = [210,11,12,12];
$arr2 = ['-','/','/'];
the code i have tried so far..
$arr1 = [210,11,12];
$arr2 = ['-','/'];
$arr3 = [];
for($i=0;$i<count($arr1);$i++){
if($i == 0){
$arr3[] = $arr1[0];
}
if ($i % 2 != 0) {
$arr3[] = $arr1[$i];
}
else {
if($i < (count($arr2)-1)){
$arr3[] = $arr2[$i];
}else{
$arr3[] = $arr2[$i-1];
}
}
}
array_push($arr3,end($arr1));
print_r($arr3);
the expected result will be
$arr3 = [210,'-',11,'/','12','/','12']
You can mix the two arrays together by converting columns to rows with array_map, then merging the rows.
$arr3 = array_merge(...array_map(null, $arr1, $arr2));
array_pop($arr3);
The array_map(null, $arr1, $arr2) expression will result in
[[210, '/'], [11, '/'], [12, '/'], [12, null]]
then, array_merge(...) combines all the inner arrays together into one for the final result.
array_pop will remove the trailing null which is there because of the uneven size of the two arrays, but if you're going to end up imploding this and outputting the results as a math expression, you don't need to do it since that won't show up anyway. In fact, if that is the goal you can just add the implode directly to the expression above.
echo implode(' ', array_merge(...array_map(null, $arr1, $arr2)));
Loop the first array and use $key =>.
Then you build the new array in the loop and if $arr2 has a value with the same key, add it after the $arr1 value.
$arr1 = [210,11,12,12];
$arr2 = ['-','/','/'];
foreach($arr1 as $key => $val){
$arr3[] = $val;
if(isset($arr2[$key])) $arr3[] = $arr2[$key];
}
var_dump($arr3);
//[210, -, 11, /, 12, /, 12]
Provided, as you say, that the second array is always larger by one element, then this would be a simple way to do it:
function foo(array $p, array $q): array {
$r = [array_shift($p)];
foreach ($q as $x) {
$r[] = $x;
$r[] = array_shift($p);
}
return $r;
}
print_r(
foo([210,11,12], ['-', '/'])
);
print_r(
foo([210,11,12,12], ['-','/','/'])
);
https://3v4l.org/F0ud8
If the indices of the arrays are well formed, the above could be simplified to:
function foo(array $p, array $q): array {
$r = [$p[0]];
foreach ($q as $i => $x) {
$r[] = $x;
$r[] = $p[$i + 1];
}
return $r;
}
I wanted to offer a couple of approaches that do not modify the original array, accommodate the possibility of empty input arrays, and do not use more than one loop.
By prepopulating the result array with the first value from the numbers array, then iterating the operators array, you can avoid making iterated checks of isset().
Code: (Demo) (Demo without iterated array_push() calls)
$numbers = [210, 11, 12];
$operators = ['-', '/'];
$result = (array)($numbers[0] ?? []);
foreach ($operators as $i => $operator) {
array_push($result, $operator, $numbers[++$i]);
}
var_export($result);
or with array_reduce():
var_export(
array_reduce(
$operators,
function($result, $operator) use($numbers) {
static $i = 0;
array_push($result, $operator, $numbers[++$i]);
return $result;
},
(array)($numbers[0] ?? [])
)
);
I have 2 arrays:
$array1 = array("dog","cat","butterfly")
$array2 = array("dogs","cat","bird","cows")
I need to get all partial matches from $array2 compared to $array1 like so:
array("dog","cat")
So I need to check if there are partial word matches in $array2 and output new array with $array1 keys and values.
array_intersection only outputs full matches
Thanks
Try this,
$array1 = array("dog","cat","butterfly");
$array2 = array("dogs","cat","bird","cows");
function partial_intersection($a,$b){
$result = array();
foreach($a as $v){
foreach($b as $val){
if( strstr($val,$v) || strstr($v,$val) ){ $result[] = $v; }
}
}
return $result;
}
print_r(partial_intersection($array1,$array2));
Some more way to get the same result
<?php
$array1 = array("dog","cat","butterfly");
$array2 = array("dogs","cat","bird","cows");
// Array output will be displayed from this array
$result_array = $array1;
// Array values are compared with each values of above array
$search_array = $array2;
print_r( array_filter($result_array, function($e) use ($search_array) {
return preg_grep("/$e/",$search_array);
}));
?>
Output
[akshay#localhost tmp]$ php test.php
Array
(
[0] => dog
[1] => cat
)