Performing an action when finding same values in two PHP arrays - php

I have two associative arrays in PHP that are defined as following:
$this_week[] = array(
"top_song_id" => $row["view_song_id"],
"top_place" => $i,
"top_move" => "0",
"top_last" => $i,
"top_peak" => $i,
"top_rating" => get_song_rating_by_id($row["view_song_id"]),
"top_views" => $row["view_sum"],
"top_start" => $monday,
"top_end" => $sunday
);
and
$last_week[] = array(
"top_song_id" => $row["view_song_id"],
"top_place" => get_song_place_by_id($row["view_song_id"]),
"top_move" => "0",
"top_last" => get_song_last_by_id($row["view_song_id"]),
"top_peak" => get_song_peak_by_id($row["view_song_id"]),
"top_rating" => get_song_rating_by_id($row["view_song_id"]),
"top_views" => $row["view_sum"],
"top_start" => $prev_monday,
"top_end" => $prev_sunday
);
Now here is my question: how can I traverse this two arrays and perform an action if there is any song id in one array that can be found in the other one?
A for() loop doesn't work because there can be common songs for both arrays but not on the same array index.
Any help is appreciated.

An efficient way to do this is to just change the first line of the last snippet this way:
$last_week[$row["view_song_id"]] = array( // Added the song id as the array index
"top_song_id" => $row["view_song_id"],
...
After that you can use a simple for loop this way:
for ($this_week as $item) {
if ( isset ($last_week[ $item["top_song_id"] ]) ) {
// HERE YOU HAVE FOUND A DUPLICATE
}
}

if( in_array( $this_week["top_song_id"], $last_week ) ) {
//do something
}

Why not just hardcode the 5(?) comparisons you need in one if statement? No need to overcomplicate things.

Related

How to remove duplicate arrays from a multi dimensional array?

I have a large multidimensional array that looks like the below.
I want to remove duplicate arrays based on the ID, however, I am struggling to achieve this.
I want the duplicates to work over the entire array, so you can see that ID 1229873 is a duplicate, in the array 2021-07-07 and 2021-07-09, it should therefore be removed from 2021-07-09
How would I achieve this? array_unique has not worked for me.
$data = array (
'2021-07-07' =>
array (
0 =>
array (
'id' => 5435435,
'homeID' => 8754,
'match_url' => '/usa/reading-united-ac-vs-ocean-city-noreasters-fc-h2h-stats#1229873',
'competition_id' => 5808,
'matches_completed_minimum' => 12,
),
1 =>
array (
'id' => 1229873,
'homeID' => 8754,
'match_url' => '/usa/reading-united-ac-vs-ocean-city-noreasters-fc-h2h-stats#1229873',
'competition_id' => 5808,
'matches_completed_minimum' => 12,
),
),
'2021-07-09' =>
array (
0 =>
array (
'id' => 3243234,
'homeID' => 8754,
'match_url' => '/usa/reading-united-ac-vs-ocean-city-noreasters-fc-h2h-stats#1229873',
'competition_id' => 5808,
'matches_completed_minimum' => 12,
),
1 =>
array (
'id' => 1229873,
'homeID' => 8754,
'match_url' => '/usa/reading-united-ac-vs-ocean-city-noreasters-fc-h2h-stats#1229873',
'competition_id' => 5808,
'matches_completed_minimum' => 12,
),
),
);
This is a perfect case for array_uunique()! No wait, scratch that. The PHP devs refused to implement it for the perfectly valid reason of... [shuffles notes] "the function name looks like a typo".
[sets notes on fire]
Anyhow, you just need to iterate over that data, keep track of the IDs you've seen, and remove entries that you've already seen.
$seen = [];
foreach(array_keys($data) as $i) {
foreach(array_keys($data[$i]) as $j) {
$id = $data[$i][$j]['id'];
if( in_array($id, $seen) ) {
unset($data[$i][$j]);
} else {
$seen[] = $id;
}
}
}
I've opted for the foreach(array_keys(...) as $x) approach as avoiding PHP references is always the sane choice.
Run it.
I am Sure That is the way which you want to get the unique array.
$unique = array_map("unserialize", array_unique(array_map("serialize", $data)));
echo "<pre>";
print_r($unique);
echo "</pre>";

Remove similar from foreach

Trying use array_unique but this did not help, since not all fields are repeated for me.
My array:
'Rows' =>
array (
0 =>
array (
'HotelId' => 94852,
'OfferId' => 858080496,
'OfferIdStr' => '858080496',
'Price' => 2762,
),
1 =>
array (
'HotelId' => 94852,
'OfferId' => 858080497,
'OfferIdStr' => '858080497',
'Price' => 3000,
),
And my try:
$allHotels['Rows'] = array_unique($allHotels['Rows'], SORT_REGULAR);
Changed flags, didn't help either (SORT_NORMAL, etc...).
It deletes absolutely everything, i need to ignore the HotelId replay, only first need.
If you want to delete duplicated entries based solely on the HotelId value, it's probably easiest just to iterate over the array, storing the seen HotelId values and deleting the current entry if it's HotelId value has already been seen.
$seenHotels = array();
foreach ($allHotels['Rows'] as $key => $hotel) {
if (in_array($hotel['HotelId'], $seenHotels)) {
unset($allHotels['Rows'][$key]);
}
else {
$seenHotels[] = $hotel['HotelId'];
}
}
print_r($allHotels);
Demo on 3v4l.org

Replace value in multidimensional php array

First, I have to say I already checked some answers but neither it wasn't exactly what I was looking for neither I couldn't fully understand the answer and how to use it.
I have this MultiDimensional array:
Array
(
[field_5abcb693a68bc] => Array
(
[0] => Array
(
[field_5abcbb1b51ddf] => mortgage
[field_5ae58a0b58b58] =>
[field_5abcbb1e51de0] => 10
[field_5abcbb2051de1] => הידגלה
[field_5abcbb2351de2] => 45,654,456
[field_5abcbb6251de3] =>
[field_5abcbb6651de4] => 04/2017
[field_5abcbb6851de5] => 4,454,656
[field_5abcbb6b51de6] => 24/07/2018
[field_5abcbbb351de7] => 657
[field_5abcbbb651de8] => 24/07/2018
[field_5abcbbb851de9] => 15
[field_5abcbbbb51dea] => yes
)
)
)
And I want to find values that much the pattern of mm/yyyy. Regex is a good option, I know how to write the condition:
if ( preg_match('/^\d[1-9]\/[1-9][0-9][0-9][0-9]$/',$v) ) {
//do stuff
}
I want to look in the inner part of the array for this pattern, and if it is a match, to change the value in the array to
$value = '01/' . $value;
means the value '04/2017' changes to '01/04/2017'.
note: there can be more than one value to change.
note: the name of the first array within the array [field_5abcb693a68bc] can vary and won't stay the same in other cases.
Thanks.
Use array_walk_recursive with reference to value as argument instead of regular value argument of callback.
It would work like that:
array_walk_recursive(
$array,
function (&$value) {
if (preg_match('/^\d[1-9]\/[1-9][0-9][0-9][0-9]$/',$value)) {
$value = '01/' . $value;
}
}
);
Check result on 3v4l.org
You want to perform a conditional replacement using a regex pattern? preg_replace() seems sensible. preg_replace() is happy to iterate a one-dimensional array, so the lowest level can be directly served to it.
Notice that I've changed the pattern delimiter to avoid escaping the forward slash. I've also made the pattern more brief by using \d and the {3} quantifier. $0 means the "fullstring match". You don't have to write the unset() call to purge those temporary variables, but some developers consider it to be best practice because it avoids potential variable conflict down-script.
Code: (Demo)
$array = [
'field_5abcb693a68bc' => [
0 => [
'field_5abcbb1b51ddf' => 'mortgage',
'field_5ae58a0b58b58' => '',
'field_5abcbb1e51de0' => '10',
'field_5abcbb2051de1' => 'הידגלה',
'field_5abcbb2351de2' => '45,654,456',
'field_5abcbb6251de3' => '',
'field_5abcbb6651de4' => '04/2017',
'field_5abcbb6851de5' => '4,454,656',
'field_5abcbb6b51de6' => '24/07/2018',
'field_5abcbbb351de7' => '657',
'field_5abcbbb651de8' => '24/07/2018',
'field_5abcbbb851de9' => '15',
'field_5abcbbbb51dea' => 'yes'
]
]
];
foreach ($array as &$set) {
foreach ($set as &$subset) {
$subset = preg_replace('~^\d[1-9]/[1-9]\d{3}$~', '01/$0', $subset);
}
}
unset($set, $subset); // avoid future variable interferences
var_export($array);
Output:
array (
'field_5abcb693a68bc' =>
array (
0 =>
array (
'field_5abcbb1b51ddf' => 'mortgage',
'field_5ae58a0b58b58' => '',
'field_5abcbb1e51de0' => '10',
'field_5abcbb2051de1' => 'הידגלה',
'field_5abcbb2351de2' => '45,654,456',
'field_5abcbb6251de3' => '',
'field_5abcbb6651de4' => '01/04/2017',
'field_5abcbb6851de5' => '4,454,656',
'field_5abcbb6b51de6' => '24/07/2018',
'field_5abcbbb351de7' => '657',
'field_5abcbbb651de8' => '24/07/2018',
'field_5abcbbb851de9' => '15',
'field_5abcbbbb51dea' => 'yes',
),
),
)
You can anonymously process down the levels of the array without actually knowing any of the names of the keys like this for example
foreach ($arr as $key => &$outer) {
foreach ($outer as &$inner) {
foreach ($inner as $k => $v) {
if ( preg_match('/^\d[1-9]\/[1-9][0-9][0-9][0-9]$/',$v) ) {
$inner[$k] = '01/' . $v;
}
}
}
}

How to insert an array to an array

I would like to add an array to within an existing array.
I am tryin to use array_push which works as long as i dont try to assign a key to the array (if i try to add a key i get a syntax error... :-()
This is my initial array:
$ResultArray = array(
"TransactionDate" => "$TransactionDate",
"tx"=>array(
"0"=>array(
"TxIndex" => "$TxIndex",
"value" => "$Value",
"PaymentConfirmedCount" => "$PaymentConfirmedCount"
),
"1"=>array(
"TxIndex" => "$TxIndex",
"value" => "$Value",
"PaymentConfirmedCount" => "$PaymentConfirmedCount"
)
)
);
i would then like to add:
$ArrayTOAdd = array(
"0"=>array(
"TxIndex" => "$TxIndex",
"value" => "$Value",
"PaymentConfirmedCount" =>
"$PaymentConfirmedCount"
)
);
if I try:
array_push($ResultArray->tx, $ArrayTOAdd);
BUT this does not work and results in a warning of "array_push() [function.array-push]: First argument should be an array"
if i try this :
array_push($ResultArray, $ArrayTOAdd);
it just adds the array but not to $ResultArray->tx
Any suggestions would be greatly welcomed!
You have to access the element in the array with $ResultArray["tx"] and not $ResultArray->tx. The second one is for the access to members in a php class. So an
array_push($ResultArray["tx"], $ArrayTOAdd);
should work.

Retrieve first key in multi-dimensional array using PHP

I would like to retrieve the first key from this multi-dimensional array.
Array
(
[User] => Array
(
[id] => 2
[firstname] => first
[lastname] => last
[phone] => 123-1456
[email] =>
[website] =>
[group_id] => 1
[company_id] => 1
)
)
This array is stored in $this->data.
Right now I am using key($this->data) which retrieves 'User' as it should but this doesn't feel like the correct way to reach the result.
Are there any other ways to retrieve this result?
Thanks
There are other ways of doing it but nothing as quick and as short as using key(). Every other usage is for getting all keys. For example, all of these will return the first key in an array:
$keys=array_keys($this->data);
echo $keys[0]; //prints first key
foreach ($this->data as $key => $value)
{
echo $key;
break;
}
As you can see both are sloppy.
If you want a oneliner, but you want to protect yourself from accidentally getting the wrong key if the iterator is not on the first element, try this:
reset($this->data);
reset():
reset() rewinds array 's internal
pointer to the first element and
returns the value of the first array
element.
But what you're doing looks fine to me. There is a function that does exactly what you want in one line; what else could you want?
Use this (PHP 5.5+):
echo reset(array_column($this->data, 'id'));
I had a similar problem to solve and was pleased to find this post. However, the solutions provided only works for 2 levels and do not work for a multi-dimensional array with any number of levels. I needed a solution that could work for an array with any dimension and could find the first keys of each level.
After a bit of work I found a solution that may be useful to someone else and therefore I included my solution as part of this post.
Here is a sample start array:
$myArray = array(
'referrer' => array(
'week' => array(
'201901' => array(
'Internal' => array(
'page' => array(
'number' => 201,
'visits' => 5
)
),
'External' => array(
'page' => array(
'number' => 121,
'visits' => 1
)
),
),
'201902' => array(
'Social' => array(
'page' => array(
'number' => 921,
'visits' => 100
)
),
'External' => array(
'page' => array(
'number' => 88,
'visits' => 4
)
),
)
)
)
);
As this function needs to display all the fist keys whatever the dimension of the array, this suggested a recursive function and my function looks like this:
function getFirstKeys($arr){
$keys = '';
reset($arr);
$key = key($arr);
$arr1 = $arr[$key];
if (is_array($arr1)){
$keys .= $key . '|'. getFirstKeys($arr1);
} else {
$keys = $key;
}
return $keys;
}
When the function is called using the code:
$xx = getFirstKeys($myArray);
echo '<h4>Get First Keys</h4>';
echo '<li>The keys are: '.$xx.'</li>';
the output is:
Get First Keys
The keys are: referrer|week|201901|Internal|page|number
I hope this saves someone a bit of time should they encounter a similar problem.

Categories