1

I'm mapping an array and based on data i'm pushing Option elements into an array as follows

 let make_children: any | null | undefined = [];
  

  buyerActivityResult && buyerActivityResult.simulcastMyAccount.data.map((item: { make: {} | null | undefined; }, key: any) => {
    make_children.push(
      <Option key={key}>{item.make}</Option>
    );
  });

Following data array has several objects and these objects have an attribute called model.

buyerActivityResult.simulcastMyAccount.data

I want to prevent pusing Options to my array if the attribute model has duplicate data. It only has to push once for all similar model values.

How can i do it?

I tried something like this

 buyerActivityResult && buyerActivityResult.simulcastMyAccount.data.map((item: { model: {} | null | undefined; }, key: any) => {
    model_children.indexOf(item.model) === -1 && model_children.push(
      <Option key={key}>{item.model}</Option>
    );
  });

But still duplicate values are being pushed into my array.

CraZyDroiD
  • 6,622
  • 30
  • 95
  • 182

2 Answers2

0

Its difficult to tell what you are trying to achieve but it looks like a map may not be the right tool for the job.

A map returns the same sized length array as that of the original array that you are calling map on.

If my assumptions are correct, your buyerActivityResult.simulcastMyAccount.data array has duplicate values, and you want to remove these duplicates based on the model property? One way to achieve this would be to use the lodash library for this, using the uniq function:

const uniqueResults = _.uniq(buyerActivityResult.simulcastMyAccount.data, (item) => item.model);
Rezaa91
  • 500
  • 2
  • 10
  • Regarding the way the question is asked, we can guess the author is inexperienced. So I think this reply has lack of explanations but it clearly does not deserve a down-vote since the answer seems to be legit and the easiest way. (Some people will say it adds a dependency but this is not the topic here). I up-voted this reply to counterbalanced the incomprehensible down-vote. – Mason Oct 04 '20 at 14:28
0

The Array.prototype.map() method is supposed to be used for manipulating the data contained into the array performing the operation. To manipulate data from other variables I recommend to use a for-loop block.

If item.model is an object, the function Array.prototype.indexOf() always returns -1 because it compares the memory address of the objects and does not do a deep comparison of all properties values.

The usual solution to remove duplicate data from an array is converting the Array into a Set then back to an Array. Unfortunately, this works only on primary type values (string, number, boolean, etc...) and not on objects.

Starting here, I will review your source code and do some changes and explain why I would apply those changes. First of all, assuming the make_children array does not receive new attribution later in your code, I would turn it into a constant. Because of the initialization, I think the declaration is overtyped.

const make_children: any[] = [];

Then I think you try to do too much things at the same time. It makes reading of the source code difficult for your colleagues, for you too (maybe not today but what about in few weeks...) and it make testing, debugging and improvements nearly impossible. Let's break it down in at least 2 steps. First one is transforming the data. For example remove duplicate. And the second one create the Option element base on the result of the previous operation.

const data: { make: any }[] = buyerActivityResult?.simulcastMyAccount?.data || [];
let options = data.map((item) => !!item.model); // removing items without model.
// Here the hard part, removing duplicates.
// - if the models inside your items have a property with unique value (like an ID) you can implement a function to do so yourself. Take a look at: https://stackoverflow.com/questions/2218999/remove-duplicates-from-an-array-of-objects-in-javascript
// - or you can use Lodash library like suggested Rezaa91 in its answer
options = _.uniq(data, (item) => item.model);

Now you only have to create the Option elements.

for (var i = 0; i < options.length; i++) {
    model_children.push(<Option key={i}>{options[i].model}</Option>);
}

// OR using the Array.prototype.map method (in this case, do not declare `model_children` at the beginning)

const model_children:[] = options.map((opt:any, i:number) => <Option key={i}>{opt.model}</Option>);

Despite the lack of context of the execution of the code you provided I hope my answer will help you to find a solution and encourage you to write clearer source code (for the sake of your colleagues and your future self).

PS: I do not know anything about ReactJs. forgive me my syntax mistakes.

Mason
  • 393
  • 7
  • 22
  • [Remove duplicates from an array of objects in JavaScript](https://stackoverflow.com/questions/2218999/remove-duplicates-from-an-array-of-objects-in-javascript) – Mason Oct 04 '20 at 15:06