Is array index rebalanced after using unset in PHP? - php

I am trying to remove duplicates from a set of tokens using unset (not considering array_unique for now), however I am getting a few issues.
$keywords = parseTweet ( $tweet );
$term_freq = array(count($keywords));
for($i = 0; $i < count($keywords); $i++){
$term_freq[$i] = 1;
for($j = 0; $j < count($keywords); $j++){
if (($i != $j) && (strcmp($keywords[$i],$keywords[$j]) == 0)){
unset ( $keywords [$j] );
unset ( $term_freq [$j] );
$term_freq[$i]++;
}
}
}
print_r ( $keywords );
print_r ( $term_freq );
I am aware of why I am getting an error; while the duplicate $j is removed, the for loop still has to reloop for the rest of the keywords and hence will fail when it encounters the missing $j. Checking the contents of the array, I found out that the index of the array skips the index $j. So it reads; [1], [2], [4], ... etc where $j = [3]
I thought that unset also rebalances the array index, am I doing something wrong or missing something completely? I am new to PHP so please bear with me!

Check if the index is set or not.
You're making needless, repetitive comparisons. Basically n² comparisons when at most n²/2 are required to compare every value in an array to every other value.
So:
$c = count($keywords)
for($i = 0; $i < $c; $i++){
$term_freq[$i] = 1;
for($j = $i+1; $j < $c; $j++){ // magic is $j = $i+1
if( ! isset($keywords[$j]) { continue; } // skip unset indices
else if ( strcmp($keywords[$i],$keywords[$j]) == 0 ){
unset ( $keywords [$j] );
unset ( $term_freq [$j] );
$term_freq[$i]++;
}
}
}
Basically you know you've already checked everything prior to $i, so you can start your inner loop at $i+1 instead of zero.
Also, you only need to count $keywords once, not n² times.

Use foreach instead of for.
foreach ($keywords as $i => $kw1){
$term_freq[$i] = 1;
foreach ($keywords as $j => $kw2){
if (($i != $j) && ($kw1 == $kw2){
unset ( $keywords [$j] );
unset ( $term_freq [$j] );
$term_freq[$i]++;
}
}
}

Related

preg_filter-implode function results in additional empty array value

I am attempting to extract image URLs from the following json - let $img_json =
[{"multi_images":"","multi_images-data-zoom-image":"/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBw%2BU0V0Y5e1tvw7%2BmfoZu8UaDNSsGcj5j0sBpr5sFzCccdMJAtF4s%2F8kDl3l7cB%2Fmg6Iwe5WT24hk%3D"},{"multi_images":"","multi_images-data-zoom-image":"/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwNSJDgIu25iaZFDdDOJGvqPHPuQLDTNDcqsaQPmMVW0RRaU9J%2FZuIdrEgh%2FX8Lgcr6Iwe5WT24hk%3D"},{"multi_images":"","multi_images-data-zoom-image":"/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwg1cMGFDnzjB9VGn8rucwG%2Fs8Snz%2BcSYyPaEAAfuwOikyZXPowLE6pZGHf%2FfvE4Hi6Iwe5WT24hk%3D"},{"multi_images":"","multi_images-data-zoom-image":"/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwKGGA7PJ5ECXgJeuxqzZBuF%2BOd2h%2FsLUgxaKeof%2BN8rl6Y03aBgKZNSzeKHO6FcK26Iwe5WT24hk%3D"},{"multi_images":"","multi_images-data-zoom-image":"/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwMcRNYUwBVM2vikrtBskkx4DcVDc%2BovLdZmEhvdbv8FLux%2FeubdmTbYiAqC5QnV9v6Iwe5WT24hk%3D"},{"multi_images":"","multi_images-data-zoom-image":"/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwUKSjnM%2F5nWK7mCv2Z6pVopKCHhtzQeUci%2FAmjauDBn7H%2B6rL7rmQCWU1G6qrWlNw6Iwe5WT24hk%3D"},{"multi_images":"","multi_images-data-zoom-image":"/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwJiL2Snf2V3JXH4QaHPSMvCgPHPbC68zHS%2BBnOfLkYDn8f9jvUcYgmsYJEKqlIr%2FK6Iwe5WT24hk%3D"},{"multi_images":"","multi_images-data-zoom-image":"/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwQybUaXaW0RsKk4MVropXFa2q28e8OYUSoyHMstGjpDLuqAN%2BudRWfSxlwgVRGvHo6Iwe5WT24hk%3D"},{"multi_images":"","multi_images-data-zoom-image":"/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwfa%2BpAsLmVxryvGCXz93nePEFwwnxdYO77XVy5fiXo%2Bf1B9l9C0CegZiiw4mofoa76Iwe5WT24hk%3D"},{"multi_images":"","multi_images-data-zoom-image":"/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwG41ol3y4AoDGIE1TCXznXSIWpbN9ANuIDtAmwZegq83opEW%2FN01wBJ86IW0CIYWI6Iwe5WT24hk%3D"}]
From these I would generate an array.
From the resulting array, I would then prepend a prefix to all the array values, the prefix being "https://www.dickerdata.com.au".
Thus I have devised the following function:
function my_get_images_dd( $img_json ) {
$img_array = json_decode( $img_json, 1 );
$all_imgs = array();
for ( $i = 0; $i <= count( $img_array ); $i++ ) {
$all_imgs[] = $img_array[ $i ]['multi_images-data-zoom-image'];
}
/*Prepend URL domain*/
/* https://stackoverflow.com/a/28115783 */
$prefixed_array = preg_filter('/^/', 'https://www.dickerdata.com.au', $all_imgs);
return implode( ",", $prefixed_array );
}
Except that the resulting output has one superfluous instance of a prefix at the very end of the array. It seems to be prefixing blank:
https://www.dickerdata.com.au/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBw%2BU0V0Y5e1tvw7%2BmfoZu8UaDNSsGcj5j0sBpr5sFzCccdMJAtF4s%2F8kDl3l7cB%2Fmg6Iwe5WT24hk%3D,https://www.dickerdata.com.au/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwNSJDgIu25iaZFDdDOJGvqPHPuQLDTNDcqsaQPmMVW0RRaU9J%2FZuIdrEgh%2FX8Lgcr6Iwe5WT24hk%3D,https://www.dickerdata.com.au/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwg1cMGFDnzjB9VGn8rucwG%2Fs8Snz%2BcSYyPaEAAfuwOikyZXPowLE6pZGHf%2FfvE4Hi6Iwe5WT24hk%3D,https://www.dickerdata.com.au/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwKGGA7PJ5ECXgJeuxqzZBuF%2BOd2h%2FsLUgxaKeof%2BN8rl6Y03aBgKZNSzeKHO6FcK26Iwe5WT24hk%3D,https://www.dickerdata.com.au/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwMcRNYUwBVM2vikrtBskkx4DcVDc%2BovLdZmEhvdbv8FLux%2FeubdmTbYiAqC5QnV9v6Iwe5WT24hk%3D,https://www.dickerdata.com.au/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwUKSjnM%2F5nWK7mCv2Z6pVopKCHhtzQeUci%2FAmjauDBn7H%2B6rL7rmQCWU1G6qrWlNw6Iwe5WT24hk%3D,https://www.dickerdata.com.au/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwJiL2Snf2V3JXH4QaHPSMvCgPHPbC68zHS%2BBnOfLkYDn8f9jvUcYgmsYJEKqlIr%2FK6Iwe5WT24hk%3D,https://www.dickerdata.com.au/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwQybUaXaW0RsKk4MVropXFa2q28e8OYUSoyHMstGjpDLuqAN%2BudRWfSxlwgVRGvHo6Iwe5WT24hk%3D,https://www.dickerdata.com.au/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwfa%2BpAsLmVxryvGCXz93nePEFwwnxdYO77XVy5fiXo%2Bf1B9l9C0CegZiiw4mofoa76Iwe5WT24hk%3D,https://www.dickerdata.com.au/Download/GetImage?encryptedURL=rA8HfbBpHU%2FJmnYa9AR4eIXySIKvdCBwG41ol3y4AoDGIE1TCXznXSIWpbN9ANuIDtAmwZegq83opEW%2FN01wBJ86IW0CIYWI6Iwe5WT24hk%3D,https://www.dickerdata.com.au
It's like there's an extra empty value in the array at the end? Why is this happening?
Edit:
Alternatively, I have used array_walk instead, with the same result
function my_get_images_dd( $img_json ) {
$img_array = json_decode( $img_json, 1 );
$all_imgs = array();
for ( $i = 0; $i <= count( $img_array ); $i++ ) {
$all_imgs[] = $img_array[ $i ]['multi_images-data-zoom-image'];
}
/*Prepend URL domain*/
/* */
array_walk($all_imgs, function(&$item) { $item = 'https://www.dickerdata.com.au'.$item; });
return implode( ",", $all_imgs );
}
You could add the string prefix in the for loop:
$all_imgs[] = 'https://www.dickerdata.com.au'.$img_array[ $i ]['multi_images-data-zoom-image'];
you need to change your for loop to $i < count( $img_array ) (not <=)
for ( $i = 0; $i < count( $img_array ); $i++ ) {
$all_imgs[] = $img_array[ $i ]['multi_images-data-zoom-image'];
}
edit:
The reason for the empty value is exactly for for loop <= (it runs the loop when $i is the same as the value of count, but array starts at zero, so it does not possess a key at count($array) (count will be 100, array ist from 0 to 99)

How to compare every value in a for loop?

I have a multidimentional array of 5 items and I want that my loop would compare it like:
1 -> 2, 1 -> 3, 1 -> 4, 1 -> 5, 2->1, 2->3, 2->4, 2->5......// so on and 5 -> 4 in the end.
The problem is that after my array $i value matches 1 and $j value matches 3, the unset is done and the $i value becomes 2 (which is correct) and $j value becomes 4 instead of 3. Could someone tell me why and what I'm doing wrong?
My loop is:
for ($i = 0; $i <= count($myArray); $i++) {
for ($j = $i+1; $j <= count($myArray); $j++) {
if (
// condition 1
&& // condition 2
) {
unset($myArray[$i]);
$i++;
}
}
}
I think that's the problem is when you unset the element in the array, you increment the counter of the loop $i. In this way, the elements of the array that are not configured are removed, this empty array position will be maintained, it will not be reordered, you will have to do it manually or using array_values ​​method.
In the last tour of the array, it will break because you are comparing the number of array elements as equal. You must use index < count($array)
The code would be like this:
for ($i = 0; $i < count($myArray); $i++) {
for ($j = $i+1; $j < count($myArray); $j++) {
if (
// condition 1
&& // condition 2
) {
unset($myArray[$i]);
// $i++;
}
}
}
try something like this
for ($i = 0; $i <= count($myArray); $i++) {
for ($j = 0; $j <= count($myArray); $j++) {
if ($j!=$i)
{
if (
// condition 1
&& // condition 2
) {
unset($myArray[$i]);
$i++;
}
}
}
}
$temp = $myArray;
for ($i = 0; $i <= count($myArray); $i++)
{
for ($j = $i + 1; $j <= count($myArray); $j++)
{
if (
// condition 1
&& // condition 2
)
{
unset($temp[$i]);
$i++;
}
}
}
print_r($temp);
Your result is in $temp. So here indexes wont get hampered, you actually are applying all operation on $temp and normally traversing $myArray.
To be honest, I do not know why nobody has yet advise to use nested foreach, since you all noticed there was a problem with array size.
foreach ($numbers as $number_horizontal_parsing) {
foreach ($numbers as $number_vertical_parsing) {
if ($number_horizontal_parsing != $number_vertical_parsing) {
//do your stuff in your case it seems you want to compare both variables
}
}
}

loop error in php code

Here is my code, and it is not removing $arr[5] element so that I am trying to remove strings starting with # from my array
this is code
<?php
$arr = [
'#EXTM3U',
'#EXTINF:177,Paul Dateh & Oren Yoel - Be More',
'Be More.mp3',
'#EXTINF:291,Christopher Toy - Just Because',
'Just Because.mp3',
'#EXTINF:238,Magnetic North - Drift Away',
'Drift Away.mp3'
];
for ($i = 0; $i <= count($arr); $i++) {
if ($arr[$i]{0} == '#') {
echo $arr[$i] . "\n";
unset($arr[$i]);
}
}
print_r($arr);
?>
Reason:- You are counting array length inside the loop and every time when any value got unset() from the array, length of array decreased and value of count($array) changed (simply decreased)
So logically your 5th and 6th element never goes through if condition (they never get traversed by loop because of decreasing length of the array )
Solution 1:- Put count outside and it will work properly:-
$count = count($arr);
//loop start from 0 so use < only otherwise, sometime you will get an undefined index error
for ($i = 0; $i < $count; $i++) {
if ($arr[$i]{0} == '#') {
//echo $arr[$i] . "\n";
unset($arr[$i]);
}
}
print_r($arr);
Output:-https://eval.in/996494
Solution 2:- That's why i prefer foreach() over for() loop
foreach($arr as $key=> $ar){
if ($ar[0] == '#') {
unset($arr[$key]);
}
}
print_r($arr);
Output:-https://eval.in/996502
more spacific :
for ($i = 0; $i < count($arr); $i++) {
if (strpos($arr[$i], '#') !== false) {
echo "<br/>";
} else {
echo $arr[$i]."<br/>";
}
}
Try to use additional array to push right values. You calc count($arr); each iteration and when you do count($arr); your array gets smaller and count($arr); returns smaller values, so last elements won't be comparing, try to use variable to calc count before loop make changes:
<?php
//...
$start_count = count($arr);
for ($i = 0; $i <= $start_count; $i++) {
if ($arr[$i]{0} == '#') {
echo $arr[$i] . "\n";
unset($arr[$i]);
}
}
Or remove bad element with a help of additional array, put good elements in new array and don't delete them from input array:
<?php
$arr = [
'#EXTM3U',
'#EXTINF:177,Paul Dateh & Oren Yoel - Be More',
'Be More.mp3',
'#EXTINF:291,Christopher Toy - Just Because',
'Just Because.mp3',
'#EXTINF:238,Magnetic North - Drift Away',
'Drift Away.mp3'
];
$cleared_from_mess_array = array();
for ($i = 0; $i <= count($arr); $i++) {
if ($arr[$i]{0} != '#')
{
array_push($cleared_from_mess_array,$arr[$i]);
}
}
print_r($cleared_from_mess_array);
exit;

How to work with nested loop in laravel

Recently I am working with nest for loop but one loop work and another not working suppose I have 2 for loop.
For example
$data =DB::table('data')->get();
$job =DB::table('job')->get();
$recruiter =DB::table('recruiter')->get();
$admin =DB::table('commission')->get();
for($i=0;i<count($job);i++){
if(!$job->isEmpty()){
for($j=0;j<count($job);j++){
if( $data[$i]->job_id == $admin[$j]->job_id )
$job[$i]=$data[$i];
}
//if checking complete then skip $i or increment it (less than count($job)) or skip
//this index $i and continue with outer loop mean i++
}
}
I had done lots of research but haven't found any solution with this kind of problem
You have missed the $ in i and j
$data = DB::table('data')->get();
$job = DB::table('job')->get();
$recruiter = DB::table('recruiter')->get();
$admin = DB::table('commission')->get();
for($i=0; $i < count( $job ); $i++){
if($job->isEmpty()){
continue;
}
for($j=0; $j < count( $job ); $j++){
if( $data[$i]->job_id == $admin[$j]->job_id ){
$job[$i]=$data[$i];
}
}
}

push elements to array while in for loop in php

How can I accomplish this in php? there are cases where I need to push more elements to the array that i'm looping through so they also get looped through:
$j = array(1,2,3);
foreach ($j as $i)
{
echo $i . "\n";
if ($i <= 3)
array_push($j, 5);
}
should print 123555 but it stops at 123.
is there a way around this in php?
foreach works on a copy of the array, not the original array (under certain conditions). That's why you're not seeing the changed reflected in the loop.
You will get the expected output when you loop by reference:
foreach ($j as &$i)
{
// ...
}
Output:
1
2
3
5
5
5
Add & to pass the reference. Default a value (copy of $j) is passed.
$j = array(1,2,3);
foreach ($j as $i=>&$v)
{
echo "$i=>$v\n";
if ($i <= 3)
array_push($j, 5);
}
PHP does not support this. From the manual:
As foreach relies on the internal array pointer changing it within the loop may lead to unexpected behavior.
http://php.net/manual/en/control-structures.foreach.php
However, this code will work, although I would not rely on this based on what the manual said.
<?
header( 'content-type: text/plain' );
$j = array(1,2,3);
foreach ($j as &$v )
{
echo "$v\n";
if ($v <= 3)
{
array_push($j, 5);
}
}
Why don't you try while:
$i = 0;
$j = array( 1, 2, 3 );
while ( count( $j ) )
{
echo array_shift( $j );
if ( $i++ <= 3 )
{
array_push( $j, 5 );
}
}

Categories