在.forEach()循环中调用唯一的随机值

时间:2019-08-06 14:20:32

标签: javascript arrays ecmascript-6 foreach

我有一个函数,可以从多种颜色中选择一种随机的颜色。

const dynamicColors = () => {
  const colors = ['#FFC100', '#FF7400', '#FF0000', '#4BBDAD', '#0C1938', '#848483'];
  const randomColor = colors[Math.floor(Math.random() * colors.length)];
  return randomColor;
};

然后我在.forEach()循环中调用此函数。

traitInfo.forEach((t) => {
    const trait = {
      id: t.id,
      label: t.label,
      lineTension: 0.1,
      fill: false,
      backgroundColor: dynamicColors(),
      borderCapStyle: 'square',
      borderJoinStyle: 'miter',
      pointHoverRadius: 8,
      pointRadius: 4,
      pointHitRadius: 10,
      data: [],
    };
    traitDatasets.push(trait);
  });

我正在创建一个图,并且使用上述技术,当然会渲染图内相同的两种或更多种颜色,这会导致UX效果不佳。

所需的输出将使backgroundColor依次显示数组中的每种颜色。 traitInfo的值永远不会超过六个。

4 个答案:

答案 0 :(得分:1)

这是您需要的吗?它会随机整理颜色并按当前的forEach索引进行选择。

// define colors somewhere
var colors - ['#FFC100', '#FF7400', '#FF0000', '#4BBDAD', '#0C1938', '#848483'];

// shuffle colors before pick and pick by 'colors[index]' of forEach
colors.sort(() => Math.random() - 0.5);
traitInfo.forEach((t,index) => {
    const trait = {
      id: t.id,
      label: t.label,
      lineTension: 0.1,
      fill: false,
      backgroundColor: colors[index],
      borderCapStyle: 'square',
      borderJoinStyle: 'miter',
      pointHoverRadius: 8,
      pointRadius: 4,
      pointHitRadius: 10,
      data: [],
    };
    traitDatasets.push(trait);
});

答案 1 :(得分:1)

const randomly = () => Math.random() - 0.5;
const colors = ['#FFC100','#FF7400','#FF0000','#4BBDAD','#0C1938','#848483'];

const traitInfo = Array(6).fill({}); // for the snippet.
const dynamicColors = [].concat(colors).sort(randomly);

traitInfo.forEach((t, i) => {
  console.info(dynamicColors[i]);
});

答案 2 :(得分:0)

使用闭包确保我不会碰到原始数组

let button = document.getElementById("button")

const dynamicColors = () => {
  const colors = ['#FFC100', '#FF7400', '#FF0000', '#4BBDAD', '#0C1938', '#848483'];
  return () => { // returns a function which returns a color
    const randomColor = colors.splice(Math.floor(Math.random() * colors.length), 1);
    // splice ensure you can't get the same color twice since it removes from the array
    return randomColor[0];
  }
}

let divs = document.querySelectorAll("div")
button.onclick = () => {
  let getColor = dynamicColors()
  Array.from(divs).forEach(div => {
    div.style.backgroundColor = getColor()
  })
}
<div id="p1">1</div>
<div id="p2">2</div>
<div id="p3">3</div>
<div id="p4">4</div>
<div id="p5">5</div>
<div id="p6">6</div>
<button id="button">colorize</button>

答案 3 :(得分:0)

您可以使用函数生成器来获取其余元素的随机元素,而不是改组,而依靠它的next元素直到done(检查其done是否为(不包括在内),假设您要为数组中的每个元素提供一个唯一值

示例工作代码:

function* colorPicker(colors) {
  while (colors && colors.length) {
    const index = Math.floor(Math.random() * colors.length);
    yield colors[index]; // <-- yields a random color.
    colors.splice(index, 1); // <-- removes the random color from the list.
  }
}

// Returns a Generator.
const cPicker = colorPicker(['#FFC100', '#FF7400', '#FF0000', '#4BBDAD', '#0C1938', '#848483']);

var test = [1,2,3,4,5,6];

// Sample usage:
test = test.map(i => ({i}));
test.forEach(trait => {
  trait.color = cPicker.next().value; // picks the next value of the generator.
});

console.log(test);

如何在代码中使用它:

traitInfo.forEach((t) => {
    const trait = {
      id: t.id,
      label: t.label,
      lineTension: 0.1,
      fill: false,
      backgroundColor: cPicker.next().value, // <-- change here
      borderCapStyle: 'square',
      borderJoinStyle: 'miter',
      pointHoverRadius: 8,
      pointRadius: 4,
      pointHitRadius: 10,
      data: [],
    };
    traitDatasets.push(trait);
  });

旁注实际上是函数*代码从数组中拼接元素:如果要使用该元素并避免丢失颜色,则应对其进行复制,或者提供数组的副本,以上代码只是另一种可行方法的示例,我认为这是一种聪明的方法。