I'm looking for an efficient algorithm for detecting equal values in an array of integers N size. It must return the indices of the matches.
Alas, I can't think of anything more clever then brute force with two loops.
Any help will be appreciated.
Thanks!
You could intersect the array. This finds all the values of array2 that are in array1
$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "red");
$array2 = array("a" => "green", "yellow", "red");
$result_array = array_intersect_assoc($array1, $array2);
print_r($result_array);
Would return
Array
(
[a] => green
)
It returns an array with all of the keys and values of the matches. Basically you can provide an infinite number of arguments to the array_insert_assoc:
array_intersect_assoc($base_array, $arr1, $arr2 ...);
It will search $base_array for the values that are in all the subsequent arrays. That means that the key and value will be taken from the $base_array
You could also compare the keys by using:
array_intersect_keys($base_array, $arr1, $arr2, $arr3);
These loops are O(N^2). Is N big? If so, can you sort the array O(NlogN), then scan it O(N)? ... or am I missing something?
You can use a set to hold the recent values. For example,
results = empty list
set = empty set
foreach key, val in array:
if val is not in set: add val to set
else: add key to results
return results
Each look up of set is O(1), so this algo will results in O(n) instead of O(n^2) if nested-loop is used.
In case you want to keep track of multi-occurence like this array 1, 2, 3, 3, 2, 1 you can use a hash table with key is the value and value (of the corresponding key in table) is the list of indices. The result for the given array will look lik {1:0, 5; 2: 1, 4; 3: 2, 3}.
results = empty hashtable
for each key, val in array:
if val is not in results:
results[val] = new list()
results[val].append(key)
return results
Perhaps this?
$arr = array_map('unserialize', array_unique(array_map('serialize', $arr)));
From the question: How to remove duplicated 2-dimension array in PHP?
if ($arr !== array_map('unserialize', array_unique(array_map('serialize', $arr))))
{
// found duplicates
}
You don't have to go through all the array again for each element. Only test an element with the subsequent element in the array:
$array = /* huge array */;
$size = count($array);
for($i = 0; $i < $size; $i++)
{
for($j = $i + 1; $j < $size; $j++) // only test with the elements after $i
{
if($array[$i] == $array[$j])
return true; // found a duplicate
}
return false; // found no duplicate
}
That's the most efficient way I can think of. Adapt it to your need as you will.
If one of your arrays is reasonably static (that is you are comparing to the same array several times ) you could invert it.
That is set up another array which is keyed by value and returns the index into the real array.
$invert = array();
foreach ($cmptoarray as $ix => $ival) {
$invert[$ival] = $ix;
}
Then you simply need an if ( isset($invert[$compfrmarray[$i]) ) .... to check the number.
Note: this is only worth doing if you compare against the same array several times!
Just use an associative array mapping a value to its index:
foreach($array1 as $index => $value) {
$aa[$value] = $index;
}
foreach($array2 as $index => $value) {
if(isset($aa[$value])) {
echo 'Duplicate: . Index 1: '.$aa[$value].' Index 2: '.$index.'.';
}
}
Related
Currently i have an array $newArr with some elements as shown in picture below. How do I know the last digit of the array index (highlighted in yellow)?
This is important because, if later I wanted to insert a new record into this $newArr array, I could just
$newArr[$the_variable_that_holds_the_last_digit + 1] = ['foo', 'bar'];
otherwise the whole array overwrite if
$newArr = ['foo', 'bar'];
I think you are looking for end pointer
$array = array(
'a' => 1,
'b' => 2,
'c' => 3,
);
end($array); // it will point to last key
$key = key($array); // get the last key using `key`
Assuming you have the numerically indexed array, the last index on your array is :
$last_index = count($newArr) -1;
if However your keys are not sequential, you can do this:
end($newArr);
$last_key = key($newArr);
I think you can try this
$array = end($newArr);
$last_index = key($array);//Its display last key of array
For more details, please follow this link.
If the only reason is to not overwrite the values you can use [] which means add new value.
$arr = [1,2,3,4];
var_dump($arr);
// incorrect way:
$arr = [1,2];
var_dump($arr);
//correct way
$arr = [1,2,3,4];
$arr[] = [1,2];
var_dump($arr);
See here for output: https://3v4l.org/ZTg28
The "correct way" will in the example above input a new array in the array.
If you want to add only the values you need to insert them one at the time.
$arr[] = 1;
$arr[] = 2;
I have a multidimensional array:
$arr = array(
array('lions', 'tigers', 'bears'), // count = 3
array('dogs', 'cats'), // count = 2
array('horses', 'pigs', 'cattle', 'sheep', 'chickens') // count = 5
);
I want to return the array with the lowest count (I don't need to know the count, just need the array that HAS the lowest count). In this case, array('dogs', 'cats')
Right now I have:
$lowest = null;
foreach($nodePath as $arr)
{
$lowest = count($arr) < count($lowest) || $lowest == null ? $arr : $lowest;
}
This works but I'm wondering if I missed a more contained solution, perhaps using array_map, array_walk or a similar function.
Use array_map() with count as a callback to get the number of elements in each array, min() to get the smallest value. Then, to get the key of the smallest array - use array_flip() to flip the arrays keys and values, and access the $minth index. Now you can use the key to get the array you need:
$counts = array_map('count', $arr);
$min = min($counts);
$key = array_flip($counts)[$min];
$smallest_arr = $arr[$key];
Demo
Map your array to another array with counts of each child array. Get the key of the minimum value in this new array. Smallest array has the key of the minimum value:
$count = array_map('count', $arr);
$min = array_keys($count , min($count))[0];
var_dump($arr[$min]); // Array ( [0] => dogs [1] => cats )
Eval.in
I want to find out the maximum value of the each key in the array
$arr1= array(
0=>array(1,2,3),
1=>array(2,4,6),
2=>array(25,4,5));
}
I want to find the maximum value for each value for the corresponding key
The final output shuld be
$max_array = array(25,4,6);
with the below code i get error max(): When only one parameter is given, it must be an array in
foreach ($res_arr as $k=>$subArray) {
foreach ($subArray as $id=>$value) {
$spanmaxArray[$id] = max($value);
}
}
First, rotate array to makes columns as lines
$arr1= array(
0=>array(1,2,3),
1=>array(2,4,6),
2=>array(25,4,5)
);
$arr2 = array();
foreach($arr1 as $subArray) {
foreach($subArray as $k=>$v) {
$arr2[$k][] = $v;
}
}
Then, use array_map as #HamZa did
$max_array = array_map('max', $arr2);
print_r($max_array);
foreach ($res_arr as $k=>$subArray){
$max = 0;
foreach ($subArray as $id=>$value){
if ($value>$max){
$max = $value;
}
}
$spanmaxArray[$k] = $max;
}
Try this.
Definitely the shortest version:
$max_array = array_map('max', $arr1);
array_map() takes each element array of $arr1 and applies max() to it.
Edited after seeing that max in each column position is desired:
$sorted = array();
for ($i = 0; $i <=2; $i++) {
$sorted[$i] = array_column($input, $i);
}
This loops over the array and applies array_column() to each (requires PHP 5.5).
So:
$sorted = array();
for ($i = 0; $i <=2; $i++) {
$sorted[$i] = array_column($arr1, $i);
}
$max_array = array_map('max', $sorted);
working version
You only need one loop, because the max function takes an array as a parameter. But the answer you are giving is wrong, unless I've misunderstood the problem.
I think what you're after is:
$max_array = array_map('max', $arr1);
All of the earlier answers are working too hard.
Use array_map() as the iterating function.
Unpack your multidimensional array with the "spread/splat operator" (...); in other words, convert your single array containing three subarrays into three separate arrays.
Call max() on the three elements as they are synchronously iterated by array_map().
Code: (Demo)
$arr1 = [
[1, 2, 3],
[2, 4, 6],
[25, 4, 5],
];
var_export(array_map('max', ...$arr1));
The above is a more versatile and concise version of the following one-liner which has the same effect on the sample array:
var_export(array_map('max', $arr1[0], $arr1[1], $arr1[2]));
Output:
array (
0 => 25,
1 => 4,
2 => 6,
)
*A note for researchers: if processing a multidimensional array that has associative first level keys, you will need to index the first level so that the splat operator doesn't choke on the keys.
...array_values($array)
I'm trying to make a function that compares two different length arrays to each other and if they match then some actions are performed. Array1, cell1 compares to array2, cell1, cell2, cellN... Then Array1, cell2 compares to array2, cell1, cell2, cellN...
Something resembling this:
if(array1[$i]==array2[])
{
// Some actions...
}
How can this be implemented?
PHP has in_array for searching an array for a particular value. So what about
foreach ($array1 as $search_item)
{
if (in_array($search_item, $array2))
{
// Some actions...
break;
}
}
You can get the difference of the Arrays with the PHP function array_diff.
<?php
$array1 = array("a" => "green", "red", "blue", "red");
$array2 = array("b" => "green", "yellow", "red");
$result = array_diff($array1, $array2);
print_r($result);
?>
Results in
Array
(
[1] => blue
)
You can use nested loops for this.
for($i=0; $i<count($array1); $i++){
for($j=0; $j<count($array2); $j++){
if($array1[$i] == $array2[$j]){
//some action here
}
}
}
kindly correct the errors. im comparing the arrays values to display respectively with their paired one
if((cardnumb1[1]==123456789) && (passcode[1]==1234))
else if ((cardnumb1[2]==987654321) && (passcode[2]==4567))
else if ((cardnumb1[3]==123789456) && (passcode[3]==7890))
Even if answered I think, just for reference, is good to know that you can make:
$array_1 = array(1,2,3,4,5);
$array_2 = array(2,4,6,8);
foreach (array_intersect($array_1,$array_2) as $match){
//do something
}
NOTE: may give some problems with associative arrays.
I need to merge several arrays into a single array. The best way to describe what I'm looking for is "interleaving" the arrays into a single array.
For example take item one from array #1 and append to the final array. Get item one from array #2 and append to the final array. Get item two from array #1 and append...etc.
The final array would look something like this:
array#1.element#1
array#2.element#1
.
.
.
The "kicker" is that the individual arrays can be of various lengths.
Is there a better data structure to use?
for example,
function array_zip_merge() {
$output = array();
// The loop incrementer takes each array out of the loop as it gets emptied by array_shift().
for ($args = func_get_args(); count($args); $args = array_filter($args)) {
// &$arg allows array_shift() to change the original.
foreach ($args as &$arg) {
$output[] = array_shift($arg);
}
}
return $output;
}
// test
$a = range(1, 10);
$b = range('a', 'f');
$c = range('A', 'B');
echo implode('', array_zip_merge($a, $b, $c)); // prints 1aA2bB3c4d5e6f78910
If the arrays only have numeric keys, here's a simple solution:
$longest = max( count($arr1), count($arr2) );
$final = array();
for ( $i = 0; $i < $longest; $i++ )
{
if ( isset( $arr1[$i] ) )
$final[] = $arr1[$i];
if ( isset( $arr2[$i] ) )
$final[] = $arr2[$i];
}
If you have named keys you can use the array_keys function for each array and loop over the array of keys instead.
If you want more than two arrays (or variable number of arrays) then you might be able to use a nested loop (though I think you'd need to have $arr[0] and $arr[1] as the individual arrays).
I would just use array_merge(), but that obviously depends on what exactly you do.
This would append those arrays to each other, while elements would only be replaced when they have the same non-numerical key. And that might not be a problem for you, or it might be possible to be solved because of attribute order, since the contents of the first arrays' elements will be overwritten by the later ones.
If you have n arrays, you could use a SortedList, and use arrayIndex * n + arrayNumber as a sort index.