php - Iterate and Skip All Values Containing The Previous Values - php

I want to check two arrays that contain similar elements. If the element in the second array containing the same element inside the first array, then save it and ignore everything after it that contain that element. And if any element in the second array is not an element of the first array and not contain any element in the first array, then save it too.
It basically is like this:
$array_1 = Array(
[0] => car,
[1] => bike,
[2] => plane,
[3] => ship
);
$array2 = Array(
[0] => tiger_claws,
[1] => bike,
[2] => bike_1,
[3] => bike_30,
[4] => bike_clone,
[5] => bike_sold,
[6] => plane,
[7] => plane_3a,
[8] => plane_fly
);
From the array examples above, I want to take tiger_claws bike and plane into new separated array that will be named $new_array. The actual data I processed is dynamic, so I need a dynamic approach too.
Here is my try to achieve it:
$count = count($array2);
$new_array = array();
for($i=0; $i<$count; $i++ ) {
foreach($array_1 as $arr){
if ($array2[$i] == $arr) {
$new_array[] = $arr;
if (strpos($array2[$i], $arr)){
continue;
}
} elseif (strpos($array2[$i], $arr) === false){
$new_array[] = $arr;
}
}
}
How do I catches the tiger_claws, bike and plane only and then put them into $new_array and leave everything else?
EDIT:
The $array2 may sometimes contain one or more elements that have underscore and that element not containing any string/ element in $array_1.
This thing is very complicated for me. Hope somebody would like to give the correct logic!
Best Regards

$new_array();
foreach ($array2 as $string) {
if (!in_array($string, $array1) &&
!in_array($string, $new_array) &&
!strpos($string, '_')) {
$new_array[] = $string;
}
}
This code loops through $array2 and checks:
if the current array value is in $array1 (if so, ignore it)
if the current array value is already in $new_array (if so, ignore it)
if the underscore '_' is not present in the current array
If so, it is added to $new_array.

Here is the solution I found. Hope someone can benefit from this answer! Please suggest me the more elegant solution if you have it.
First, we check if there are any element of $array_1 that is contained in $array2 and collect them to a new array if there is matched element:
$check = array();
foreach(array2 as $arr){
foreach($array_1 as $arr1){
if($arr == $arr1) {
$check[] = $arr;
}
}
}
Next, do the filtering with the new array created above and save the elements we want into $new_array
$new_array = array();
foreach(array2 as $arr){
foreach($check as $chk){
if($arr == $chk || strpos($arr, $chk) === false) {
$new_array[] = $arr;
}
}
}
Now, the $new_array elements will be:
tiger_claws,
bike,
plane
About strpos. According to my test and the reference here, !strpos($var1, $var2) is not the correct opposite of strpos($var1, $var2). This is an example of the correct way to test if strpos is false:
if(strpos($var1, $var2) === false) {
// do your stuff
}

Related

Split flat array into grouped subarrays containing values from consecutive key in the input array

I have an array from array_diff function and it looks like below:
Array
(
[0] => world
[1] => is
[2] => a
[3] => wonderfull
[5] => in
[6] => our
)
As you can see, we have a gap between the keys #3 and #5 (i.e. there is no key #4).
How can I split that array into 2 parts, or maybe more if there are more gaps?
The expected output would be:
Array
(
[0] => Array
(
[0] => world
[1] => is
[2] => a
[3] => wonderfull
)
[1] => Array
(
[0] => in
[1] => our
)
)
You can use old_key,new_key concept to check that there difference is 1 or not? if not then create new index inside you result array otherwise add the values on same index:-
<?php
$arr = Array(0 => 'world',1 => 'is',2 => 'a',3 => 'wonderfull',5 => 'in',6 => 'our');
$new_array = [];
$old_key = -1;
$i = 0;
foreach($arr as $key=>$val){
if(($key-$old_key) ==1){
$new_array[$i][] = $val;
$old_key = $key;
}
if(($key-$old_key) >1){
$i++;
$new_array[$i][] = $val;
$old_key = $key;
}
}
print_r($new_array);
https://3v4l.org/Yl9rp
You can make use of the array internal pointer to traverse the array.
<?php
$arr = Array(0=>"world",1=>"is",2=>"a",3=>"wonderfull",5=>"in",6=>"our");
print_r($arr);
$result = Array();
$lastkey;
while($word = current($arr))
{
$key = key($arr);
if(isset($lastkey) && $key == $lastkey + 1)
{
$result[count($result) - 1][] = $word;
}
else
{
$result[] = Array($word);
}
$lastkey = $key;
next($arr);
}
print_r($result);
?>
This task is a perfect candidate for a reference variable. You unconditionally push values into a designated "bucket" -- in this case a subarray. You only conditionally change where that bucket is in the output array.
There are two important checks to make when determining if a new incremented key should be generated:
if it is not the first iteration and
the current key minus (the previous key + 1) does not equal 0.
Code: (Demo)
$nextKey = null;
$result = [];
foreach ($array as $key => $val) {
if ($nextKey === null || $key !== $nextKey) {
unset($ref);
$result[] = &$ref;
}
$ref[] = $val;
$nextKey = $key + 1;
}
var_export($result);
This solution generates an indexed array starting from zero with my sample input and uses only one if block. In contrast, AliveToDie's solution generates a numerically keyed array starting from 1 and uses two condition blocks containing redundant lines of code.

How to skip iteration in foreach inside foreach

I have an array of values, and i want to insert the values to another array but with an if condition, if the "if" is true I want to skip the iteration.
Code:
$array=array(array(1=>11,2=>22,3=>23,4=>44,5=>55));
$insert=array();
foreach($array as $k1=>$v1)
{
foreach($v1 as $k2=>$v2)
{
if($v2==23)
{
break;
}
}
$insert[]=$v1;
}
final result should look like that
Array
(
[0] => Array
(
[1] => 11
[2] => 22
[3] => 44
[4] => 55
)
)
I tried using: break,return,continue...
Thanks
There are a few ways to do this. You can loop over the outer array and use array_filter on the inner array to remove where the value is 23 like this (IMO preferred; this also uses an array of $dontWant numbers so it is easier to add or change numbers later):
<?php
$array = array(array(1=>11,2=>22,3=>23,4=>44,5=>55));
$insert = array();
//array of numbers you don't want
$dontWant = array(23);
//loop over outer array
foreach($array as $subArray){
//add to $insert a filtered array
//subArray is filtered to remove where value is in $dontWant
$insert[] = array_filter($subArray, function($val) uses ($dontWant) {
//returns true if the value is not in the array of numbers we dont want
return !in_array($val, $dontWant);
});
}
//display final array
echo '<pre>'.print_r($insert,1).'</pre>';
Or you can reference the first key to add to a sub array in $insert like (which is a little more like what your code is trying to do and show that you are not too far off):
<?php
$array = array(array(1=>11,2=>22,3=>23,4=>44,5=>55));
$insert = array();
//loop over outer array
foreach($array as $k1=>$v1){
//add an empty array to $insert
$insert[$k1] = array();
//loop over inner array
foreach($v1 as $k2=>$v2){
//if the inner array value is not 23
if($v2 != 23){
//add to inner array in insert
$insert[$k1][] = $v2;
}
}
}
//display the result
echo '<pre>'.print_r($insert,1).'</pre>';
Both of these methods would produce the same result. IMO using array_filter is the preferred method, but the second method might be a little easier to understand for someone new to programming.
Why don't you just try it like this?
foreach($v1 as $k2=>$v2)
{
if($v2!=23)
{
$insert[]=$v2;
}
}
EDIT:
Explanation: You check with the if($v2!=23) if the value of the variable $v2 is not equal to (that is the != sign) any given number that stands after the inequality operator, and if so, it will insert that value to the array $insert.
I hope it is clear now.
Sorry, I've written $v1 instead of $v2, the code should work now.
To add variants :)
$array=array(array(1=>11,2=>22,3=>23,4=>44,5=>55));
$insert=array();
foreach($array as $a)
{
while (($i = array_search(23, $a)) !== false)
{ unset($a[$i]); sort($a); }
$insert[] = $a;
}
print_r($a);
result:
Array ( [0] => Array ( [0] => 11 [1] => 22 [2] => 44 [3] => 55 ) )

PHP Compare 2 arrays checking if part of value exist in the other one

I looked in the forum and found a lot of almost same topics but not what I am exactly looking for:
I have 1 array like:
$filterNames : Array
(
[0] => 11424205969default-img.jpg
[1] => myimage.png
[2] => media/14-15/11235231video1.flv
[3] => likemedia/10-12/233569video2.mp4
)
Another like:
$files : Array
(
[0] => /mypath/materiales/media/14-15/video1.flv
[1] => /mypath/materiales/likemedia/10-12/video2.mp4
)
I need to get the array of the values wich are not already existing in 1st array. But as the values are not identical I can't get it work.
Something like:
function array_check($files, $keyword) {
$out = array();
foreach($files as $index => $string) {
if (strpos($string, $keyword) !== FALSE) {
foreach ($filterNames as $namesF) {
$out[] = array_check(array($files,'stackoverflow'),$namesF);
}
}
}
}
My question is diferent on the one presented by AbraCadaver because the values of arrays are not exactly same, in the example, they are all same (numbers)
I need an output array with only the single values like they are in the $files array, with exact path. But not if present with another path in the 1st array.
Do I explain myself ?
thanks for helping guys
cheers
I'm not sure what the expected output of this would be, but here is an example. In the example the 'match' array would be a key value array with these values :
[
'thing-one.jpg'] => 0
]
Where the value (0) is the key (Belonging to arr2) where the match was found. You could use a simple "in_array()" search using the key ('thing-one.jpg') to get the key where it appears in arr1.
$arr1 = [
[0] => 'folder/other-thing/thing-one.jpg'
[1] => 'folder/other-thing/thing-two.prj'
[2] => 'folder/other-thing/thing-three.png'
];
$arr2 = [
[0] => 'omg/lol/thing-one.jpg',
[1] => 'omg/lol/thing-eight.wtf'
];
function findAllTheThings($arr1, $arr2) {
$match = [];
foreach ($arr1 as $path) {
$sub_strings = explode('/', $path);
foreach ($sub_strings as $piece) {
if (in_array($piece, $arr2)) {
// we have a match in the path
$match[$piece] = in_array($piece, $arr2);
}
}
}
}
Thanks for your time and answer.
First, php give me an error with the $match = []; so I put array();
Then I put the code adding a return line, but $out array is empty.
function findAllTheThings($arr1, $arr2) {
$match = array();
foreach ($arr1 as $path) {
$sub_strings = explode('/', $path);
foreach ($sub_strings as $piece) {
if (in_array($piece, $arr2)) {
// we have a match in the path
$match[$piece] = in_array($piece, $arr2);
}
}
}
return $match;
}
$out = findAllTheThings($filterNames, $files);
Still digging ;)
thanks for help
EDIT :
THanks guys.
I need an array wich gives
$files : Array
(
[0] => /mypath/materiales/media/14-15/video1.flv
[1] => /mypath/materiales/likemedia/10-12/video2.mp4
)
In fact I have an array with these values and I need to filter to exclude all files already in the DB.
This array is to insert in db. but don't want to have twice the files even if already exist in DB
do I explain myself ?
thanks for help

PHP address array tree node using string or array

Say, I have data in a tree structure implemented as an array of arrays to an arbitrary depth, something like
print_r($my_array);
Array
(
[id] => 123
[value] => Hello, World!
[child] => Array
(
[name] => Foo
[bar] => baz
)
[otherchild] => Array
(
[status] => fubar
[list] => Array
(
[one] => 1
[two] => 3
)
)
[sanity] => unchecked
)
Now, using a single string as key I would like to address a node at an arbitrary depth, Let's say I have a key something like this:
$key = 'otherchild|list|two';
Using this key I want to be able to address the value stored in
$my_array['otherchild']['list']['two']
Obviously I can explode('|', $key) to get an array of keys, and shifting values off of this and using those to address sub-arrays makes it easy to obtain the value I'm looking for, something like
$value = $my_array;
$keys = explode('|', $key);
while ($k = array_shift($keys)) {
if (isset($value[$k])) {
$value = $value[$k];
} else {
// handle failure
}
} // Here, if all keys exist, $value holds value of addressed node
But I'm stuck trying to update values in a generic way, ie without having to resort to something like
$keys = explode('|', $key);
if (count($keys) == 1) {
$my_array[$keys[0]] = $new_value;
} else if (count($keys) == 2) {
$my_array[$keys[0]][$keys[1]] = $new_value;
} else if ...
Any ideas?
function setAt(array & $a, $key, $value)
{
$keys = explode('|', $key);
// Start with the root node (the array itself)
$node = & $a;
// Walk the tree, create nodes as needed
foreach ($keys as $k) {
// Create node if it does not exist
if (! isset($node[$k])) {
$node[$k] = array();
}
// Walk to the node
$node = & $node[$k];
}
// Position found; store the value
$node = $value;
}
// Test
$array = array();
// Add new values
setAt($array, 'some|key', 'value1');
setAt($array, 'some|otherkey', 'val2');
setAt($array, 'key3', 'value3');
print_r($array);
// Overwrite existing values
setAt($array, 'some|key', 'new-value');
print_r($array);
setAt($array, 'some', 'thing');
print_r($array);
If you're looking for a short answer, you can also use eval().
$elem = "\$array['" . str_replace("|", "']['", $key) . "']";
$val = eval("return isset($elem) ? $elem : null;");

Add two arrays with the same length

I have two arrays,
$arr_1 = array(01=>5, 02=>3, 03=>2);
$arr_2 = array(01=>3, 02=>4, 03=>0);
what I want to achieve is to have a single array where the final form after adding the two arrays would be,
$arr_3 = array(01=>8, 02=>7, 03=>2);
I tried array_merge but it wasn't the solution.How would I attain the final form?
Try array_map. From the PHP Manual
array_map() returns an array containing all the elements of arr1
after applying the callback function to each one. The number of
parameters that the callback function accepts should match the number
of arrays passed to the array_map()
$arr_1 = array(01=>5, 02=>3, 03=>2);
$arr_2 = array(01=>3, 02=>4, 03=>0);
$arr_3 = array_map('add', $arr_1, $arr_2);
function add($ar1, $ar2){
return $ar1+$ar2;
}
print_r($arr_3);
OUTPUT:
Array ( [0] => 8 [1] => 7 [2] => 2 )
A for loop should handle this:
$max = count($arr_1);
$arr_3 = array();
for($i = 0; $i < $max; $i++){
$arr_3[$i] = intval($arr_1[$i]) + intval($arr_2[$i]);
}
I'm sure there are many other ways to do this, but this is the first one that came to mind. You could also do a foreach loop:
$arr_3 = array();
foreach($arr_1 as $k => $v){
$arr_3[$k] = intval($v) + intval($arr_2[$k]);
}
I'm just winging it here, the foreach is a little tricky to avoid the cartesian effects. Worth a shot though.
If you require adding elements matching by their key not by their position, you could try this:
$array1 = array(1=>5, 2=>3, 3=>2);
$array2 = array(3=>3, 2=>4, 1=>0); //unsorted array
$keys_matched = array_intersect_key ( $array1 , $array2);
foreach ($keys_matched as $key => $value) {
$result[$key] = $array1[$key] + $array2[$key];
}
print_r($result); //Displays: Array ( [1] => 5 [2] => 7 [3] => 5
You would look through both arrays and add each value of each array together then add that result to another array.
foreach($array1 as $val1) {
foreach($array2 as $val2) {
array_push($newArray, intval($val1)+ intval(val2));
}
}

Categories