0

I am trying to randomize colors by generating random number, then applying it to array to get an color array containing font-color and background-color.

At every "skill" I want to have unique color scheme. So each time I loop skill array I loop color array to fetch color scheme. If this color scheme number (which is same as the randomNumber) is already in use I random again. I do this with do/while loop. When color is not found it pushes it to usedColors array and paints the picture.

For some reason I am still getting same colors. I pasted two pictures to the bottom. Console.log image is about usedColors array (the randomly generated numbers)

var usedColors = [];
    $.each(knowledges, (i, knowledge) => {                                  
       do {
          var r = Math.floor(Math.random() * Math.floor(colors.length)),
              rColors = colors[r];                

          } while ($.inArray(r, usedColors) == 0);
          usedColors.push(r);

          $("#knowledges div").append(            
              $("<p />").addClass("knowledge").text(knowledge).css({"background-color": rColors[0], "color": rColors[1]})
          );
    });

enter image description here

enter image description here

Jaakko Uusitalo
  • 655
  • 1
  • 8
  • 21
  • I haven't used the jQuery `inArray` function, but the docs say: " If the first element within the array matches value, $.inArray() returns 0." It looks like you are only checking if the value matches the first element. You need to check if it's not equal to (or greater than) -1. [inArray Docs](https://api.jquery.com/jQuery.inArray/) – Mark May 22 '18 at 06:11
  • Others already give you a possible solution for your problem. An alternative algorithm would be to reshuffle the colors array, and then just use colors[i] to get a random color – NoBBy May 22 '18 at 06:17

4 Answers4

0

inArray gives position of the matching element. So compare against -1, to know that element is not present in the usedColors array.

var usedColors = [];

$.each(knowledges, (i, knowledge) => {                                  
   do {
      var r = Math.floor(Math.random() * Math.floor(colors.length)),
          rColors = colors[r];                

      } while ($.inArray(r, usedColors) != -1);
      usedColors.push(r);

      $("#knowledges div").append(            
          $("<p />").addClass("knowledge").text(knowledge).css({"background-color": rColors[0], "color": rColors[1]})
      );
});
Shivaji Varma
  • 690
  • 13
  • 24
0

In your while loop, are you checking if the array is unique? If so, it looks like you may not be using $.inArray correctly.

Put this in your while loop:$.inArray(r, usedColors) !== -1

jQuery.inArray(), how to use it right?

Jordan Daniels
  • 4,896
  • 1
  • 19
  • 29
0

To generate array of unique numbers from certain interval you can do this. In your case the range will be 0, arr.length - 1.

// function that will generate random unique random numbers between start 
// and end, and store already generated numbers in closure
function generateUniqueRandom(start, end) {
  const used = [];

  function generateInner() {
    let r;
    while (!r) {
      r = Math.floor(Math.random() * (end - start) + 1) + start;
      if (used.includes(r)) {
        r = null;
      } else {
        used.push(r);
      }
    }

    return r;
  }

  return generateInner;
}

const random1 = generateUniqueRandom(0, 20);

const nums1 = [];
for (let i = 0; i < 10; i++) {
  nums1.push(random1());
}

console.log(nums1);

const random2 = generateUniqueRandom(0, 20);

const nums2 = [];
for (let i = 0; i < 20; i++) {
  nums2.push(random2());
}

console.log(nums2);

But you need to be careful not to generate more numbers that the specified range is, otherwise you will be stuck in an infinite loop.

Matus Dubrava
  • 13,637
  • 2
  • 38
  • 54
0

I think your loop method has many interactions, I mean your loop is traveling so much that it only ends until you find the random number that is not in the array (A short performance problem). An alternative method so that the array elements are random:

function shuffleArray(a) {
    for (let i = a.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [a[i], a[j]] = [a[j], a[i]];
    }
    return a;
}

const colors = [["black","green"], ["white","blue"], ["pink","white"]];
let usedColors = shuffleArray(colors);

//You can now do this:

$.each(knowledges, (i, knowledge) => {
    $("#knowledges div").append(            
        $("<p />").addClass("knowledge").text(knowledge).css({"background-color": usedColors[i][0], "color": usedColors[i][1]})
    );
});