有异常的唯一数组

Unique array with exception

我有一个非常具体的问题。我花了很多时间让它工作,但我没有成功。

Here is piece of my code, how it looks now:

var mainNames = ["James", "Robert", "John", "Michael", "William", "David", "Peter", "Joseph"];
var genNames = [];

var exceptionNames = ["James", "Michael", "David", "Robert"];

    for (var i = 0; i < 4; i++)
    {
        var idx = Math.floor(Math.random() * names .length);

        genNames.push(names [idx]);
    }

What I need to do?

How do I print the final list?

Here are some possible correct outputs:

感谢 solutions/answers!

对初始数组和 select 前 4 项进行随机排序。然后将项目与异常数组进行比较,确保计数为 1 或更小。不断重复找到解决方案。

var mainNames = ["James", "Robert", "John", "Michael", "William", "David", "Peter", "Joseph"];
var exceptionNames = ["James", "Michael", "David", "Robert"];
let names = [], count = 4
while(count>1) {
  names = mainNames.map(i => ({ s: Math.random(), i })).sort((a,b) => a.s - b.s).map(({i})=> i).slice(4);
  count = names.filter(n => exceptionNames.includes(n)).length;
}
console.log(names.join(','))

我想你可以这样做,但它会有点慢不知道你的名字数组最终会有多大。

let mainNames = [
  'James',
  'Robert',
  'John',
  'Michael',
  'William',
  'David',
  'Peter',
  'Joseph',
]
let genNames = []

const exceptionNames = ['James', 'Michael', 'David', 'Robert']

let exceptionNameAlreadyIncluded = false
while (genNames.length < 4) {
  // if the variable exceptionNameAlreadyIncluded is true we filter our the exception names
  // to leave only the "normal" ones
  const namesToSearch = exceptionNameAlreadyIncluded
    ? mainNames.filter(
        (name) => !exceptionNames.some((exName) => exName === name),
      )
    : mainNames
    
  // belowe we get random name from our filtered ones push it to the genNamesArray
  // and we remove it from mainNames array so there is no duplicates
  const nameToAdd = namesToSearch[getRandomInt(namesToSearch.length)]
  mainNames = mainNames.filter((name) => name != nameToAdd)
  genNames = [...genNames, nameToAdd]

  // if the name we found using random is one of exception names we set our
  // exceptionNameAlreadyIncluded to true to not include any exception names in future randoms
  if (exceptionNames.some((name) => name === nameToAdd))
    exceptionNameAlreadyIncluded = true
}

console.log(genNames)

function getRandomInt(max) {
  return Math.floor(Math.random() * max)
}

更快的解决方案

let mainNames = [
  'James',
  'Robert',
  'John',
  'Michael',
  'William',
  'David',
  'Peter',
  'Joseph',
]
let genNames = []

const exceptionNames = ['James', 'Michael', 'David', 'Robert']

let exceptionNameAlreadyIncluded = false
while (genNames.length < 4) {
  const nameIndex = getRandomInt(mainNames.length)
  const isExceptionName = exceptionNames.some(
    (name) => name === mainNames[nameIndex],
  )
  if (!exceptionNameAlreadyIncluded || !isExceptionName) {
    genNames.push(mainNames[nameIndex])
  }
  if (isExceptionName) exceptionNameAlreadyIncluded = true
  mainNames.splice(nameIndex, 1)
}

console.log(genNames)

function getRandomInt(max) {
  return Math.floor(Math.random() * max)
}

首先,您的代码中似乎存在一些语法错误 - 例如,在您尝试使用变量之前,“名称”永远不会 created/initialized。我认为它应该是“mainNames”。

变量和方法调用之间也不能有空格。例如'names .length' 应该是 'names.length' 而 'names [idx]' 应该是 'names[idx].

除此之外,您还缺少任何方法来检查所选名称是否已在列表中。获得随机索引后,将其转换为一个值,然后在继续之前检查它是否符合您列出的标准(如果它不在列表中)。有多种方法可以做到这一点,但这是您缺少的最重要的一步。

然后您还需要添加一种方法来检查您的异常名称是否只出现一次。同样,有几种方法可以做到这一点,但目前完全没有这一步。

如果您遇到这样的问题,我强烈建议您在直接进入实际代码之前,先在 pseudo-code 中(用通俗易懂的注释)写下您需要完成的步骤。这真的可以帮助保持事情的顺利进行。