Home > Blockchain >  Applying color with index in forEach loop
Applying color with index in forEach loop

Time:04-15

Let's say i have array of the colors;

availableColors = ['#aee3d8', ' #d1caae', '#e7e1f9'];

and I have the array of the Objects with object like this.

[{
        name: 'Name',
        surname: 'Surname',
        timeOff: '8:05 AM',
        imageSource: null,
    };
{
        name: 'Name',
        surname: 'Surname',
        timeOff: '8:05 AM',
        imageSource: someUrl,
    };

{
        name: 'Name',
        surname: 'Surname',
        timeOff: '8:05 AM',
        imageSource: null,
    }]

How can I apply the different color by index when mapping user?

    public applyUserPictureColor(): void {
    this.users.push(this.user, this.user, this.user, this.user);
    const users = this.users.map((user) => {
        if (!user.imageSource) {
            return {
                ...user,
                bg: this.colorIndex(),
            };
        }
    });
this.users = users;
}



private colorIndex(): void {
        this.availableColors
    }

CodePudding user response:

You could use a Generator and Iterator to do this kind of thing.

This will always repeat the colors provided in the array given to *getColor() for however many users you have. It does this using and ininfite loop and modular arithmetic.

const availableColors = ["#aee3d8", "#d1caae", "#e7e1f9"];

/**
 * Cyclic generator to always get the next color from a given range of colors.
 * @param {Array<string>} allColors
 */
function* getColor(allColors) {
  let i = 0;
  while (true) {
    yield allColors[i];
    i = (i   1) % allColors.length;
  }
}

// get the iterator to be able to always get the next color
const iter = getColor(availableColors);

const users = [
  {
    name: "Name",
    surname: "Surname",
    timeOff: "8:05 AM",
    imageSource: "",
  },
  {
    name: "Name2",
    surname: "Surname",
    timeOff: "8:05 AM",
    imageSource: "",
  },
  {
    name: "Name3",
    surname: "Surname",
    timeOff: "8:05 AM",
    imageSource: "",
  },
  {
    name: "Name4",
    surname: "Surname",
    timeOff: "8:05 AM",
    imageSource: null,
  },
  {
    name: "Name5",
    surname: "Surname",
    timeOff: "8:05 AM",
    imageSource: "",
  },
  {
    name: "Name6",
    surname: "Surname",
    timeOff: "8:05 AM",
    imageSource: null,
  },
];

const usersWithColors = users.map(user => {
  // use iterator to get next color
  user.backgroundColor = iter.next().value;
  return user;
})

console.log(usersWithColors);

This will also not start at the "beginning" again like you want it to behave, except when you create a new iterator.

const availableColors = ["#aee3d8", "#d1caae", "#e7e1f9"];

/**
 * Cyclic generator to always get the next color from a given range of colors.
 * @param {Array<string>} allColors
 */
function* getColor(allColors) {
  let i = 0;
  while (true) {
    yield allColors[i];
    i = (i   1) % allColors.length;
  }
}

let iterator = getColor(availableColors);
for (let index = 0; index < 5; index  ) {
  console.log(iterator.next().value);
}
// the next value of iterator.next().value would be #e7e1f9
// but now we assign a new iterator and start from the beginning again
iterator = getColor(availableColors);
console.log("Start over...")
for (let index = 0; index < 2; index  ) {
  console.log(iterator.next().value);
}

Edit

As Nick Parsons pointed out you can make the generator more elegant by using the following.

/**
 * Cyclic generator to always get the next color from a given range of colors.
 * @param {Array<string>} allColors
 */
function* getColor(allColors) {
  while (true) yield* allColors;
}

Also if you want to treat your array as immutable, which you usually would like to do, you need to adjust the map() function as shown below.

const usersWithColors = users.map(user => ({ ...user, backgroundColor: iter.next().value }))

Applying all of the above you will get to the following implementation:

const availableColors = ["#aee3d8", "#d1caae", "#e7e1f9"];

/**
 * Cyclic generator to always get the next color from a given range of colors.
 * @param {Array<string>} allColors
 */
function* getColor(allColors) {
  while (true) yield* allColors;
}

// get the iterator to be able to always get the next color
const iter = getColor(availableColors);

const users = [
  {
    name: "Name",
    surname: "Surname",
    timeOff: "8:05 AM",
    imageSource: "",
  },
  {
    name: "Name2",
    surname: "Surname",
    timeOff: "8:05 AM",
    imageSource: "",
  },
  {
    name: "Name3",
    surname: "Surname",
    timeOff: "8:05 AM",
    imageSource: "",
  },
  {
    name: "Name4",
    surname: "Surname",
    timeOff: "8:05 AM",
    imageSource: null,
  },
  {
    name: "Name5",
    surname: "Surname",
    timeOff: "8:05 AM",
    imageSource: "",
  },
  {
    name: "Name6",
    surname: "Surname",
    timeOff: "8:05 AM",
    imageSource: null,
  },
];

const usersWithColors = users.map(user => ({ ...user, backgroundColor: iter.next().value }))
// this is now a new array
console.log("New array with background color information")
console.log(usersWithColors);
// users is not changed
console.log("Unchanged users")
console.log(users)

  • Related