简体   繁体   中英

Altering array while iterating over

I have the following code:

for (let word in words) {
  for (let i = 0; i < words.length; i++) {
    // something
    words.splice(i, 1);
    i--;
  }
}

And i'm wounder how could i still continue the outer iteration, even if i'm changing the size with splice. I read that i could achieve that with a reverse iteration, but this solution only works for one loop, not two.

Thanks.

If you're removing elements, it would be best to iterate over the array backwards.

From our discussion you're needing to compare the element to each other element, and based on some business logic (represented as a random 10% in the below code) will reject a word from the supplied array.

JS

let words = ["one", "two", "three", "four", "five", "six"]; // 100.000 strings 

for (let x = words.length - 1; x >= 0; x--) {
    // if we're trying to access an element that no longer exists
    if (typeof words[x] === 'undefined') continue;
    for (let y = words.length - 1; y >= 0; y--) {
        // if we're trying to access an element that no longer exists
        if (typeof words[y] === 'undefined') continue;
        // if word should be rejected
        console.log('Comparing: ' + words[x] + ' ' + words[y]);
        if (shouldRejectWordB(words[x], words[y])) {
            // remove the word
            console.log('Rejecting: ' + words[y]);
            words.splice(y, 1);
        }
    }
}
console.log(JSON.stringify(words));

function shouldRejectWordB(wordA, wordB) {
    // reject word randomly
    if (Math.random() < 0.1) {
        return true;
    } else {
        return false;
    }
}

JS FIDDLE


UPDATE FOR EFFICIENCY

Upon thinking about this further, a recursive function seems like a more efficient solution than the one above. Above simply continue 's any element it encounters that is at an undefined index. So we are still accessing n^2 elements as we process. Alternatively, if we pass the current list of words into a recursive function as an argument, along with wordA to compare it to, we can reduce negate attempts to access removed words, speeding up later iterations as items are removed.

JS

let words = ["one", "two", "three", "four", "five", "six"]; // 100.000 strings 

function shouldRejectWordB(wordA, wordB) {
    // reject word randomly
    if (Math.random() < 0.1) {
        return true;
    } else {
        return false;
    }
}

function compareWordAToEachWord(wordA, words){
    // loop through each provided word
    for (let y = words.length - 1; y >= 0; y--) {
        // if word should be rejected
        console.log('Comparing: ' + wordA + ' ' + words[y]);
        var wordToCompare = words[y];
        if (shouldRejectWordB(wordA, wordToCompare)) {
            // remove the word
            console.log('Rejecting: ' + wordToCompare);
            words.splice(y, 1);
            // if we just rejected the word that is currently set as wordA stop comparing this loop
            if(wordToCompare === wordA){
                break;
            }
        }
    }
    if(words.length){
        // the index of the current wordA
        var index = words.indexOf(wordA);
        // suggested index of the next word
        var newIndex = words.length - 1;
        console.log('index: '+index+' suggestion: '+newIndex);
        // if the suggestion is the same or greater than the current word, get the item before the current word
        if(index <= newIndex){
            newIndex = index-1;
        }
        // if our suggestion is not for an element before the first (ie. invalid), begin another comparison
        if(newIndex >= 0){
            compareWordAToEachWord(words[newIndex], words);
        }else{
            // we have completed out looping through all words for comparison
            console.log(JSON.stringify(words));
        }
    }
}

console.log(JSON.stringify(words));
// kick start the comparison with the last word in the list
compareWordAToEachWord(words[words.length - 1], words);

UPDATED FIDDLE

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM