how to compare arrays for additions and subtractions in php? - php

I have two arrays:
$currentArr = ['apples','oranges','pears'];
$newArr = ['apples','oranges','pears', 'grapes'];
I need to formulate logic that will:
a) check the $newArr against the $currentArr and tell me what was REMOVED and what was ADDED
b) push the removed values onto a new separate array and push the added values onto a new separate array
as I am not extremely well versed in PHP, is this possible? if so, how can I do so?

array_diff() is what you need:
Returns an array containing all the entries from array1 that are not present in any of the other arrays.
<?php
$currentArr = ['apples','oranges','pears','test'];
$newArr = ['apples','oranges','pears', 'grapes'];
$removed = array_diff($currentArr, $newArr);
print_r($removed);
// output:
// Array ( [3] => test )
// switch the order to get the added items:
$added = array_diff($newArr, $currentArr);
print_r($added);
// output:
// Array ( [3] => grapes )

arr_diff($a,$b) is a function that returns a new array containing the items in $a that are not in $b.
$removed = array_diff($currentAr,$newArr);
$added = array_diff($newArr,$currentAr);

Related

php array of arrays to 1D array not getting properly as expected

I am reading value from CMD which is running a python program and my output as follows:
Let as assume those values as $A:
$A = [[1][2][3][4]....]
I want to make an array from that as:
$A = [1,2,3,4....]
I had tried as follows:
$val = str_replace("[","",$A);
$val = str_replace("]","",$val);
print_r($val);
I am getting output as:
Array ( [0] => 1 2 3 4 ... )
Please guide me
try this
// your code goes here
$array = array(
array("1"),
array("2"),
array("3"),
array("4")
);
$outputArray = array();
foreach($array as $key => $value)
{
$outputArray[] = $value[0];
}
print_r($outputArray);
Also check the example here https://ideone.com/qaxhGZ
This will work
array_reduce($a, 'array_merge', array());
Multidimensional array to single dimensional array,
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($A));
$A = iterator_to_array($it, false);
But, if $A is string
$A = '[[1][2][3][4]]';
$A = explode('][', $A);
$A = array_map(function($val){
return trim($val,'[]');
}, $A);
Both codes will get,
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
This function will work when you do indeed have a multidimensional array, which you stated you have, in stead of the String representation of a multidimensional array, which you seem to have.
function TwoDToOneDArray($TwoDArray) {
$result = array();
foreach ($TwoDArray as $value) {
array_push($result, $value[0]);
}
return $result;
}
var_dump(TwoDToOneDArray([[0],[1]]));
You can transform $A = [[1],[2],[3],[4]] into $B = [1,2,3,4....] using this following one line solution:
$B = array_map('array_shift', $A);
PD: You could not handle an array of arrays ( a matrix ) the way you did. That way is only for managing strings. And your notation was wrong. An array of arrays (a matrix) is declared with commas.
If you have a string like you wrote in the first place you can try with regex:
$a = '[[1][2][3][4]]';
preg_match_all('/\[([0-9\.]*)\]/', $a, $matches);
$a = $matches[1];
var_dump($a);
If $A is a string that looks like an array, here's one way to get it:
$A = '[[1][2][3][4]]';
print "[".str_replace(array("[","]"),array("",","),substr($A,2,strlen($A)-4))."]";
It removes [ and replaces ] with ,. I just removed the end and start brackets before the replacement and added both of them after it finishes. This outputs: [1,2,3,4] as you can see in this link.

How to delete duplicates in an array?

How can I delete duplicates in array?
For example if I had the following array:
$array = array('1','1','2','3');
I want it to become
$array = array('2','3');
so I want it to delete the whole value if two of it are found
Depending on PHP version, this should work in all versions of PHP >= 4.0.6 as it doesn't require anonymous functions that require PHP >= 5.3:
function moreThanOne($val) {
return $val < 2;
}
$a1 = array('1','1','2','3');
print_r(array_keys(array_filter(array_count_values($a1), 'moreThanOne')));
DEMO (Change the PHP version in the drop-down to select the version of PHP you are using)
This works because:
array_count_values will go through the array and create an index for each value and increment it each time it encounters it again.
array_filter will take the created array and pass it through the moreThanOne function defined earlier, if it returns false, the key/value pair will be removed.
array_keys will discard the value portion of the array creating an array with the values being the keys that were defined. This final step gives you a result that removes all values that existed more than once within the original array.
You can filter them out using array_count_values():
$array = array('1','1','2','3');
$res = array_keys(array_filter(array_count_values($array), function($freq) {
return $freq == 1;
}));
The function returns an array comprising the original values and their respective frequencies; you then pick only the single frequencies. The end result is obtained by retrieving the keys.
Demo
Try this code,
<?php
$array = array('1','1','2','3');
foreach($array as $data){
$key= array_keys($array,$data);
if(count($key)>1){
foreach($key as $key2 => $data2){
unset($array[$key2]);
}
}
}
$array=array_values($array);
print_r($array);
?>
Output
Array ( [0] => 2 [1] => 3 )
PHP offers so many array functions, you just have to combine them:
$arr = array_keys(array_filter(array_count_values($arr), function($val) {
return $val === 1;
}));
Reference: array_keys, array_filter, array_count_values
DEMO
Remove duplicate values from an array.
array_unique($array)
$array = array(4, "4", "3", 4, 3, "3");
$result = array_unique($array);
print_r($result);
/*
Array
(
[0] => 4
[2] => 3
)
*/

How to append output of preg_match to an existing array?

I have two preg_match() calls and i want to merge the arrays instead of replacing the first array. my code so far:
$arr = Array();
$string1 = "Article: graphics card";
$string2 = "Price: 300 Euro";
$regex1 = "/Article[\:] (?P<article>.*)/";
$regex2 = "/Price[\:] (?P<price>[0-9]+) Euro/";
preg_match($regex1, $string1, $arr);
//output here:
$arr['article'] = "graphics card"
$arr['price'] = null
preg_match($regex2, $string2, $arr);
//output here:
$arr['article'] = null
$arr['price'] = "300"
How may I match so my output will be:
$arr['article'] = "graphics card"
$arr['price'] = "300"
?
You could use preg_replace_callback and handle the merging inside the callback function.
If it were me this is how I would do it, this would allow for easier extension at a later date, and would avoid using a callback function. It could also support searching one string easily by replacing $strs[$key] and the $strs array with a singular string var. It doesn't remove the numerical keys, but if you are only ever to go on accessing the associative keys from the array this will never cause a problem.
$strs = array();
$strs[] = "Article: graphics card";
$strs[] = "Price: 300 Euro";
$regs = array();
$regs[] = "/Article[\:] (?P<article>.*)/";
$regs[] = "/Price[\:] (?P<price>[0-9]+) Euro/";
$a = array();
foreach( $regs as $key => $reg ){
if ( preg_match($reg, $strs[$key], $b) ) {
$a += $b;
}
}
print_r($a);
/*
Array
(
[0] => Article: graphics card
[article] => graphics card
[1] => graphics card
[price] => 300
)
*/
You can use array_merge for this if you store your results in two different arrays.
But your output depicted above is not correct. You do not have $arr['price'] if you search with regex1 in your string but only $arr['article']. Same applies for the second preg_match.
That means if you store one result in $arr and one in $arr2 you can merge them into one array.
preg_match does not offer the functionality itself.
Use different array for second preg_match ,say $arr2
Traverse $arr2 as $key => $value .
Choose non null value out of $arr[$key] and $arr2[$key], and write that value to $arr[$key].
$arr will have required merged array.
This should work for your example:
array_merge( // selfexplanatory
array_filter( preg_match($regex1, $string1, $arr)?$arr:array() ), //removes null values
array_filter( preg_match($regex2, $string2, $arr)?$arr:array() )
);

How do I remove a specific key in an array using php?

I have an array with 4 values. I would like to remove the value at the 2nd position and then have the rest of the key's shift down one.
$b = array(123,456,789,123);
Before Removing the Key at the 2nd position:
Array ( [0] => 123 [1] => 456 [2] => 789 [3] => 123 )
After I would like the remaining keys to shift down one to fill in the space of the missing key
Array ( [0] => 123 [1] => 789 [2] => 123 )
I tried using unset() on the specific key, but it would not shift down the remaining keys. How do I remove a specific key in an array using php?
You need array_values($b) in order to re-key the array so the keys are sequential and numeric (starting at 0).
The following should do the trick:
$b = array(123,456,789,123);
unset($b[1]);
$b = array_values($b);
echo "<pre>"; print_r($b);
It is represented that your input data is an indexed array (there are no gaps in the sequence of the integer keys which start from zero). I'll compare the obvious techniques that directly deliver the desired result from the OP's sample data.
1. unset() then array_values()
unset($b[1]);
$b = array_value($b);
This is safe to use without checking for the existence of the index -- if missing, there will be no error.
unset() can receive multiple parameters, so if more elements need to be removed, then the number of function calls remains the same. e.g. unset($b[1], $b[3], $b[5]);
unset() cannot be nested inside of array_values() to form a one-liner because unset() modifies the variable and returns no value.
AFAIK, unset() is not particularly handy for removing elements using a dynamic whitelist/blacklist of keys.
2. array_splice()
array_splice($b, 1, 1);
// (input array, starting position, number of elements to remove)
This function is key-ignorant, it will target elements based on their position in the array. This is safe to use without checking for the existence of the position -- if missing, there will be no error.
array_splice() can remove a single element or, at best, remove multiple consecutive elements. If you need to remove non-consecutive elements you would need to make additional function calls.
array_splice() does not require an array_values() call because "Numerical keys in input are not preserved" -- this may or may not be desirable in certain situations.
3. array_filter() nested in array_values()
array_values(
array_filter(
$b,
function($k) {
return $k != 1;
},
ARRAY_FILTER_USE_KEY
)
)
This technique relies on a custom function call and a flag to tell the filter to iterate only the keys.
It will be a relatively poor performer because it will iterate all of the elements regardless of the logical necessity.
It is the most verbose of the options that I will discuss.
It further loses efficiency if you want to employ an in_array() call with a whitelist/blacklist of keys in the custom function.
Prior to PHP7.4, passing a whitelist/blacklist/variable into the custom function scope will require the use of use().
It can be written as a one-liner.
This is safe to use without checking for the existence of the index(es) -- if missing, there will be no error.
4. array_diff_key() nested in array_values()
array_values(
array_diff_key(
$b,
[1 => '']
)
);
This technique isn't terribly verbose, but it is a bit of an overkill if you only need to remove one element.
array_diff_key() really shines when there is a whitelist/blacklist array of keys (which may have a varying element count). PHP is very swift at processing keys, so this function is very efficient at the task that it was designed to do.
The values in the array which is declared as the second parameter of array_diff_key() are completely irrelevant -- they can be null or 999 or 'eleventeen' -- only the keys are respected.
array_diff_key() does not have any scoping challenges, compared to array_filter(), because there is no custom function called.
It can be written as a one-liner.
This is safe to use without checking for the existence of the index(es) -- if missing, there will be no error.
Use array_splice().
array_splice( $b, 1, 1 );
// $b == Array ( [0] => 123 [1] => 789 [2] => 123 )
No one has mentioned this, so i will do: sort() is your friend.
$fruits = array("lemon", "orange", "banana", "apple");
sort($fruits);
foreach($fruits as $key => $val)
echo "fruits[$key] = $val";
output:
fruits[0] = apple
fruits[1] = banana
fruits[2] = lemon
fruits[3] = orange
// remove Lemon, too bitter
unset($fruits[2]);
// keep keys with asort
asort($fruits);
foreach($fruits as $key => $val)
echo "fruits[$key] = $val";
Output:
fruits[0] = apple
fruits[1] = banana
fruits[3] = orange
This is the one you want to use to reindex the keys:
// reindex keys with sort
sort($fruits);
foreach($fruits as $key => $val)
echo "fruits[$key] = $val";
Output:
fruits[0] = apple
fruits[1] = banana
fruits[2] = orange
If you want to remove an item from an array at a specific position, you can obtain the key for that position and then unset it:
$b = array(123,456,789,123);
$p = 2;
$a = array_keys($b);
if ($p < 0 || $p >= count($a))
{
throw new RuntimeException(sprintf('Position %d does not exists.', $p));
}
$k = $a[$p-1];
unset($b[$k]);
This works with any PHP array, regardless where the indexing starts or if strings are used for keys.
If you want to renumber the remaining array just use array_values:
$b = array_values($b);
Which will give you a zero-based, numerically indexed array.
If the original array is a zero-based, numerically indexed array as well (as in your question), you can skip the part about obtaining the key:
$b = array(123,456,789,123);
$p = 2;
if ($p < 0 || $p >= count($b))
{
throw new RuntimeException(sprintf('Position %d does not exists.', $p));
}
unset($b[$p-1]);
$b = array_values($b);
Or directly use array_splice which deals with offsets instead of keys and re-indexes the array (numeric keys in input are not preserved):
$b = array(123,456,789,123);
$p = 2;
if ($p < 0 || $p >= count($b))
{
throw new RuntimeException(sprintf('Position %d does not exists.', $p));
}
array_splice($b, $p-1, 1);

Want to got the new array that not in array A?

I have two arrays:
$A = array('a','b','c','d')
$c = array('b','c','e','f')
I want to get a new array containing items not in array $A. So it would be:
$result = array('e','f');
because 'e' and 'f' are not in $A.
Use array_diff
print_r(array_diff($c, $A)); returns
Array
(
[2] => e
[3] => f
)
Use array_diff for this task. As somewhat annoying it does not return all the differences between the two arrays. Only the elements from the first array passed which are not found in any other array passed as argument.
$array1 = array('a','b','c','d');
$array2 = array('b','c','e','f');
$result = array_diff($array2, $array1);
array_diff()
Pseduo Code for General Implementation
Disclaimer: Not familiar with PHP, other answers indicate there are a lot quicker ways of doing this :)
Loop through your first array:
// Array of results
array results[];
// Loop through all chars in first array
for i = 0; i < A.size; i++
{
// Have we found it in second array yet?
bool matched = false;
// Loop each character in 2nd array
for j = 0; j < C.size; j++
{
// If they match, exit the loop
if A[i] == C[J] then
matched = true;
exit for;
}
// If we have a match add it to results
if matches == true then results.add(A[i])
}

Categories