简体   繁体   中英

Removing random element from an array /Javascript

I googled my question but found no answer, thank you in advance for help. The thing is, I have some code that works ok, but I would like to improve it:

function go(times) {
    function pick(n) {
        return n[Math.floor(Math.random() * n.length)];
    }

    var body = ["face", "nose", "hair", "smile"];
    var adj = ["amazing", "nice", "beautiful", "perfect"];
    var word = ["great", "innocent", "glowing", "adorable"];

    var str = "Your " + pick(body) + " looks " + pick(adj) + " and " + pick(word) + "!";
    if (times > 0) {
        for (i = 0; i < times; i++) {
            str = str + " And " + go().toLowerCase();
        }
    }

    return str;
}

When the random word is picked, it should be removed from an array so there won't be any repeation. I can handle it with splice function if I know exact index of element, but when it's random it doesn't work how I want it to.

You can easily add a function to all arrays to return a random value and/or remove one randomly.

// After this, you can call.getRandomValue() on any array!
Array.prototype.getRandomValue = function(removeItem) {
    if (this.length < 1) throw "Cannot get random value from zero-length array";
    var randomIndex = Math.floor(Math.random() * this.length);
    var randomValue = this[randomIndex];
    if (removeItem)
        this.splice(randomIndex, 1);
    return randomValue;
};

function constructDescription(sentenceCount) {
    var body = ["face", "nose", "hair", "smile"];
    var adj = ["amazing", "nice", "beautiful", "perfect"];
    var word = ["great", "innocent", "glowing", "adorable"];    

    var description = "";

    for(var i = 0; i < sentenceCount; i++) {
      if (body.length > 0 && adj.length > 0 && word.length > 0) {
        description += (description.length > 0) ? " And your " : "Your ";
        description += body.getRandomValue(true) + " looks " + adj.getRandomValue(true) + " and " + word.getRandomValue(true) + "!"         
      }    
    }

    return description;
}

Try it out with a Fiddle here.

You just need to combine your splice and your randomizer. example:

function go(times) {

    var body = ["face", "nose", "hair", "smile"];
    var adj = ["amazing", "nice", "beautiful", "perfect"];
    var word = ["great", "innocent", "glowing", "adorable"];

    function pick(n) {
        return n.splice(Math.floor(Math.random() * n.length), 1);
    }

    var str = "";

    for (var i = 0; i < times; i++) {
        str += (i > 0 ? " And your ":"Your ") + pick(body) + " looks " + pick(adj) + " and " + pick(word) + "!";
    }

    return str;
}

Use a different function instead of calling go() recursively in the loop. By calling go() for each phrase you initialize the original arrays each time. Then do the splicing in pick()

 function go(times) { var body = ["face", "nose", "hair", "smile"]; var adj = ["amazing", "nice", "beautiful", "perfect"]; var word = ["great", "innocent", "glowing", "adorable"]; var str = '' function pick(n) { var idx = Math.floor(Math.random() * n.length); var str = n[idx]; n.splice(idx, 1) return str; } function getPhrase(i) { var phrase = pick(body) + " looks " + pick(adj) + " and " + pick(word) + "!"; return i == 0 ? "Your " + phrase : " And your " + phrase; } for (var i = 0; i < times; i++) { str += getPhrase(i); } return str; } document.body.innerHTML = go(4); 

@lucounu solution is absolutely spot on.

In case if you just wanted to improve upon your initial solution , you could have done the following :

    var body = ["face", "nose", "hair", "smile"];
    var adj = ["amazing", "nice", "beautiful", "perfect"];
    var word = ["great", "innocent", "glowing", "adorable"];

    function go(times) {

    function pick(n) {
        var index =  Math.floor(Math.random() * n.length)
        var randomString  = n[index];
        n.splice(index,1);
        return randomString;
    }

    var str = "Your " + pick(body) + " looks " + pick(adj) + " and " + pick(word) + "!";

    if (times > 0) {
        for (i = 0; i < times; i++) {
            str = str + " And " + go().toLowerCase();
        }
    }

    return str;
}

console.log(go(2));

Give it a try

var data = ["brain", "mitochondria", "microsope", "beaker", "beaker-2", "scientist", "cell", "atom"];

    while (data.length) {
        document.write(data.splice(data.length * Math.random() | 0, 1)[0] + '<br>');
    }

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