【问题标题】:Set key of random objects to a different value将随机对象的键设置为不同的值
【发布时间】:2019-11-02 17:28:25
【问题描述】:

我得到一个输入 = 5。

我想将此数组中的 5 个随机对象的 is_winner 键设置为 true。

const participants = [
    {code: '111111', is_winner: false},
    {code: '222222', is_winner: false},
    {code: '444444', is_winner: false},
    {code: '777777', is_winner: false},
    {code: '555555', is_winner: false},
    {code: '666666', is_winner: false},
    {code: '333333', is_winner: false},
    {code: '888888', is_winner: false},
    {code: '999999', is_winner: false},
];

第一次随机化:

const participants = [
    {code: '111111', is_winner: false},
    {code: '222222', is_winner: true},
    {code: '444444', is_winner: false},
    {code: '777777', is_winner: true},
    {code: '555555', is_winner: false},
    {code: '666666', is_winner: true},
    {code: '333333', is_winner: true},
    {code: '888888', is_winner: false},
    {code: '999999', is_winner: true},
];

我尝试了以下有 2 个 for 循环,其中一个是 O(n^2)

const winners = [];

while (winners.length < 5) {
    const randomParticipant = participants[Math.floor(Math.random() * participants.length)];

    if (!winners.includes(randomParticipant.code)) {
        winners.push(randomParticipant.code);
    }
}

for (let participant of participants) {
    if (winners.includes(participant.code)) {
        participant.is_winner = true;
    }
}

看看有没有更高效的方法。

【问题讨论】:

  • 看起来像家庭作业。不久前,他发布了一个类似的问题。 SOF 不是作业解决工具
  • @mwilson 我在问题中发布了我的解决方案。我正在努力变得更好,看看那里有什么。感谢您的理解。
  • 创建一个从0participants.length-1 的数字数组。打乱数组,取前 5 个元素,并使用它们作为索引来更改 is_winner
  • winners.includes() 是 O(n),所以你的整个算法是 O(n^2)。使用 Set 而不是数组来解决这个问题。

标签: javascript arrays algorithm object ecmascript-6


【解决方案1】:
// Found a nice way to shuffle in this SOF post https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array
const shuffle = (array) => {
    for (let i = array.length - 1; i > 0; i--) {
        let j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
    return array
};

// Selects random participants and set their is_winner key to true.
const setRandomWinners = (numberOfWinners) => {
    const arr = [...Array(participants.length).keys()];
    const shuffledArr = shuffle(arr);
    const newArr = shuffledArr.slice(0, numberOfWinners);

    for (let el of newArr) {
        participants[el].is_winner = true;
    }
};

【讨论】:

    【解决方案2】:

    您也可以考虑使用SetArray.forEach 执行此操作,如下所示:

    const participants = [ {code: '111111', is_winner: false}, {code: '222222', is_winner: false}, {code: '444444', is_winner: false}, {code: '777777', is_winner: false}, {code: '555555', is_winner: false}, {code: '666666', is_winner: false}, {code: '333333', is_winner: false}, {code: '888888', is_winner: false}, {code: '999999', is_winner: false}, ];
    
    let randomize = (arr, n=5, clone=true) => {
      let set = new Set(), _arr = arr
      if(clone) _arr = arr.map(x => ({...x})) // skip if you want to mutate
      while(set.size < n) set.add(Math.floor(Math.random() * participants.length))
      Array.from(set).forEach(x => _arr[x].is_winner = true)
      return _arr
    }
    
    console.log(randomize(participants))
    console.log(randomize(participants, 3))

    Setwhile 负责生成随机数数组(在您的情况下为数组索引)。一旦你有了它,你只需通过Array.forEachis_winner 设置为true

    由于函数最好不要改变输入,因此我添加了 clone 标志,但如果您不关心它,您可以删除它以及仅创建数组克隆的 if(clone) 行。

    【讨论】:

      猜你喜欢
      • 2017-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-16
      • 1970-01-01
      • 2022-12-10
      • 1970-01-01
      相关资源
      最近更新 更多