0

I have an array "source"

source : [
{
    "id": 1,
    "secondId": 1
},
{
    "id": 2,
    "secondId": 1
},
{
    "id": 3,
    "secondId": 1
}
]

I want to rename the secondId when there are duplicate like this:

[
{
    "id": 1,
    "secondId": 1
},
{
    "id": 2,
    "secondId": 1_2
},
{
    "id": 3,
    "secondId": 1_3
}
]

I have this so far:

for (i = 0 ; i < source.length ; i++) {
  for (j = 0 ; j < source.length ; j++){

    if (source[i]["id"] != source[j]["id"] && source[i]["secondId"] === source[j]["secondId"]){
        source[j]["secondId"] += "_" + (i+1);
    }
    console.log(source[j]["secondId"]);

  }
}

and I'm getting:

[
{
    "id": 1,
    "secondId": 1
},
{
    "id": 2,
    "secondId": 1_2
},
{
    "id": 3,
    "secondId": 1_2_3
}
]

I tried to use some:

if(source[j]["secondId"].includes("_"+ (i+1))){
    console.log(source[j]["secondId"].split("_"+ (i+1)).shift());
}

but I'm getting:

"secondId": 1 "secondId": 1 "secondId": 1_2

How can I do it? Any tips please?

6
  • 1
    Is the ID a string or a number? Because it's awfully weird to de-duplicate by turning 1 into 12 and 13 and so on... Commented Mar 18, 2022 at 14:51
  • There are numbers, for the example I put small number but secondId could be bigger. I try to renamed it with "_", so it could be 436_1 and 436_2 when there are duplicate secondId Commented Mar 18, 2022 at 14:56
  • 1
    But... the _ doesn't do anything in numbers! 1_2 is the same thing as 12, and 436_1 is the same thing as 4361. I'm asking what's the reason behind de-duplicating them like this. Commented Mar 18, 2022 at 14:58
  • 1
    Specifically, I guess, when you can already identify an object by its unique id why would you need to change the second id? Commented Mar 18, 2022 at 15:04
  • @Andy it's like "id" would be for a category and "secondId" for products (but the products could be of different colors) Commented Mar 18, 2022 at 15:21

3 Answers 3

2

A version using Array.reduce:

let source = [
{
    "id": 1,
    "secondId": 1
},
{
    "id": 2,
    "secondId": 1
},
{
    "id": 3,
    "secondId": 1
}];

let output = Object.values(
  source.reduce((a, e, i) => {
    let testId = e.secondId.toString();
    if (a[testId]) {
      testId = testId.split("_")[0] + "_" + (i + 1);
    }
    a[testId] = {...e, secondId: testId};
    return a;
  }, {})
);

console.log(output);

Sign up to request clarification or add additional context in comments.

Comments

1

This may be a solution to achieve the (assumed) desired objective:

Code Snippet

const markDupes = arr => (
  arr.reduce(
    (fin, {id, secondId}) => ({
      tm: {
        [secondId]: (fin.tm[secondId] || 0) + 1
      },
      newArr: [
        ...fin.newArr,
        {id, secondId: secondId.toString() + (
          fin.tm[secondId] > 0 ? `_${fin.tm[secondId]+1}` : ''
        )}
      ]
    }),
    { tm: {}, newArr: [] }
  )?.newArr
);


const source = [{
    "id": 1,
    "secondId": 1
  },
  {
    "id": 2,
    "secondId": 1
  },
  {
    "id": 3,
    "secondId": 1
  }
];


console.log(markDupes(source));

Explanation

  • Use .reduce to iterate over the array of objects
  • Set up an initial fin object with two props tm (tracking-map) and newArr (the result-array which will have the secondId updated as desired)
  • For each object, destructure to directly access id and secondId
  • Update the map tm based on the secondId with a counter
  • Append to the newArr an object with id and secondId props with the latter (secondId) being converted to a string to store values of the format 1_2, 1_3, etc

NOTE: This may not be an optimal solution.

Comments

1

When you convert 1 to 1_2 or 1_3 it is converting a number to a string which will be a huge pain when you have a use for the number later. Instead what i have done is convert that number to a decimal for as 1.2 ,1.3 which means you can do all sorts of computation on a number without much conversion

let source = [
    {
        "id": 1,
        "secondId": 1
    },
    {
        "id": 2,
        "secondId": 1
    },
    {
        "id": 3,
        "secondId": 1
    }
];

let val = {};
for (const i in source) {
    let v = source[i].secondId
    val[v] = val[v] ? val[v] : v
    if (val[v] !== 1) {
        console.log(source[i].id, v);
        source[i].secondId = Number(v.toFixed(2)) + (val[v] * 0.1)
    }
    val[v]++
}
console.log(source);

if you are really kean of using string instead use source[i].secondId = v+'_'+val[v] instead inside the if by changing the original source json object as well

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.