-1

I have an JS Object that is built up as followed props.moves:

0: {userId: 168, moveId: 198, moveName: "FirstSettlementMove", building: {…}}
1: {userId: 168, moveId: 200, moveName: "FirstSettlementMove", building: {…}}
2: {userId: 168, moveId: 202, moveName: "FirstSettlementMove", building: {…}}
3: {userId: 168, moveId: 204, moveName: "FirstSettlementMove", building: {…}}
4: {userId: 168, moveId: 206, moveName: "FirstSettlementMove", building: {…}}

I want to write a specific function that goes through all elements of this object so starting from 0 to the last one. And with that it should check for the value in moveName and put all unique ones into an array and return that array. So basically something like:

function moveCollector(props.moves) {
        let arr = [];
           for (key=="moveName" in props.moves)
              add every unique value to arr
    }

Has anyone an approach or solution for that? I am especially clueless about the part with the unique values and the fact that one object element has various keys.

Thanks in advance!

  • 1
    Does this answer your question? [How to get distinct values from an array of objects in JavaScript?](https://stackoverflow.com/questions/15125920/how-to-get-distinct-values-from-an-array-of-objects-in-javascript) – Emile Bergeron May 04 '20 at 17:46

4 Answers4

1

let moves = [
{userId: 168, moveId: 198, moveName: "FirstSettlementMove"},
{userId: 168, moveId: 200, moveName: "FirstSettlementMove"},
{userId: 168, moveId: 202, moveName: "FirstSettlementMove"},
{userId: 168, moveId: 204, moveName: "FirstSettlementMove"},
{userId: 168, moveId: 206, moveName: "FirstSettlementMove"}
]

function moveCollector(moves) {
     let unique=[]
     moves.forEach((move)=>{
       if(!unique.includes(move.moveName )){
             unique.push(move.moveName );
        }
     })
    return unique;
}

console.log("unique names of moves:",moveCollector(moves))

you can do something like this

 function moveCollector(moves) {
     let unique=[]
     moves.forEach((move)=>{
       if(!unique.includes(move.moveName )){
             unique.push(move.moveName );
        }
     })
    return unique;
}
Jatin Parmar
  • 2,759
  • 5
  • 20
  • 31
1

You could use reduce() to create an object with the names as keys and read the keys:

let names = Object.keys(list.reduce((acc, v) => {
  acc[v.moveName] = 1;
  return acc;
}, {}))

list = [{userId: 168, moveId: 198, moveName: "FirstSettlementMove"},
{userId: 168, moveId: 200, moveName: "FirstSettlementMove"},
{userId: 168, moveId: 202, moveName: "FirstSettlementMove"},
{userId: 168, moveId: 204, moveName: "FirstSettlementMove"},
{userId: 168, moveId: 206, moveName: "FirstSettlementMove"}]

let names = Object.keys(list.reduce((acc, v) => {
  acc[v.moveName] = 1;
  return acc;
}, {}))

console.log(names);

Or you could use Set:

let names = Array.from(list.reduce((acc, v) => acc.add(v.moveName), new Set()))

    list = [{userId: 168, moveId: 198, moveName: "FirstSettlementMove"},
    {userId: 168, moveId: 200, moveName: "FirstSettlementMove"},
    {userId: 168, moveId: 202, moveName: "FirstSettlementMove"},
    {userId: 168, moveId: 204, moveName: "FirstSettlementMove"},
    {userId: 168, moveId: 206, moveName: "FirstSettlementMove"}]

    let names = Array.from(list.reduce((acc, v) => acc.add(v.moveName), new Set()))

    console.log(names);
Jason Goemaat
  • 28,692
  • 15
  • 86
  • 113
1

It might be easier to start with a slightly simpler problem, and work your way up. Suppose we want to write a function unique that takes an array of numbers, and produces another array of numbers containing one of each of the unique values in the input array. That is:

// *wishful thinking*

unique([1, 3, 1, 1, 2, 3, 4, 3, 4])
// => [1, 3, 2, 4]

One way is to iterate through the input array, maintaining an array of numbers that we have seen so far. For each number, if we have not yet seen it, we add it to the array; otherwise, we move on. Here's what that might look like;

function unique(nums) {
  const seen = [];
  for (let num of nums) {
    if (!seen.includes(num)) {
      seen.push(num);
    }
  }
  return seen;
}

Now, to answer your question we will need to modify this function in one key way: in order to test whether an object should be added to the seen array, we need to see if another object with the same moveName value has already been seen. We can accomplish this using the find method:

function unique(objs) {
  const seen = [];
  for (let obj of objs) {
    if (!seen.find(({ moveName }) => moveName === obj.moveName)) {
      seen.push(obj);
    }
  }
  return seen;
}

It would be remiss of me to not mention that this can also be achieved by way of the reduce method:

function unique(objs) {
  return objs.reduce((acc, obj) => (
    acc.find(({ moveName }) => obj.moveName === moveName)
    ? acc
    : [...acc, obj]
  ), []);
}

Some prefer this; others abhor it.

William Lewis
  • 537
  • 4
  • 9
0

Another way for people who like one line code:)

const moveCollector = (props.moves) =>
     props.moves.reduce(
       (acc, move) =>
         !acc.includes(move.moveName)
          ? [...acc, move.moveName]
          : acc,
       []
     );
Loppik
  • 328
  • 2
  • 8
  • This doesn't work. It throws an error since you're not returning the `acc` and `includes` gets called on `acc` every iteration. – Emile Bergeron May 04 '20 at 17:34