-1

I need to update this array and get the data according to the reference_id once the order is been updated accordingly the order should be displayed according to the display priority.

this is the data that I am getting from the API.

[
  { id: 3, name: 'hello world', reference_id: null, display_priority: 10},
  { id: 6, name: 'hello world', reference_id: 2 , display_priority: 30},
  { id: 1, name: 'hello world', reference_id: 2, display_priority: 40 },
  { id: 4, name: 'hello world', reference_id: null, display_priority: 80},
  { id: 2, name: 'hello world', reference_id: null, display_priority: 100 },
  { id: 5, name: 'hello world', reference_id: 3, display_priority: 110 },
]

I need to reorder this array into something similar to this.

[
  { id: 3, name: 'hello world', reference_id: null, display_priority: 10 },
  { id: 5, name: 'hello world', reference_id: 3, display_priority: 110 },
  { id: 4, name: 'hello world', reference_id: null, display_priority: 80 },
  { id: 2, name: 'hello world', reference_id: null, display_priority: 100 },
  { id: 6, name: 'hello world', reference_id: 2, display_priority: 30},
  { id: 1, name: 'hello world', reference_id: 2, display_priority: 40},
]

I need to match the id with the reference_id and then if there is any reference_id the related items should be below the matched Id. when listing the items it should be listed according to the display_priority as an example

  { id: 2, name: 'hello world', reference_id: null },
  { id: 6, name: 'hello world', reference_id: 2, display_priority: 30},
  { id: 1, name: 'hello world', reference_id: 2, display_priority: 40},

This is the code that I tried

    var product={product_skus:
    [
        { id: 1, name: 'hello world', reference_id: 2, display_priority: 40 },
  { id: 2, name: 'hello world', reference_id: null, display_priority: 100 },
  { id: 3, name: 'hello world', reference_id: null, display_priority: 10},
  { id: 4, name: 'hello world', reference_id: null , display_priority: 80},
  { id: 5, name: 'hello world', reference_id: 3, display_priority: 110 },
  { id: 6, name: 'hello world', reference_id: 2 , display_priority: 30},
    ]};
const reorderedArray = test.reduce((acc, current) => {
      const referenceId = current.reference_id;
      if (referenceId === null) {
        const referencedChildIndex = acc.findIndex(item => item.reference_id === current.id);
        if (referencedChildIndex !== -1) {
          acc.splice(referencedChildIndex, 0, current);
        } else {
          acc.push(current);
        }
      } else {
        const referencedIndex = acc.findIndex(item => item.id === referenceId);
        if (referencedIndex !== -1) {
          acc.splice(referencedIndex + 1, 0, current);
        } else {
          acc.push(current);
        }
      }
      return acc;
    }, []);

console.log(reorderedArray);

but I am not getting the expected output.

rasif sahl
  • 172
  • 1
  • 8

2 Answers2

1

Your code only works when the child elements are after their parents in the original array, because if the parent is not found in the accumulator you just push the current element.

To fix your code you could do:

let test = [
  { id: 1, name: 'hello world', reference_id: 2 },
  { id: 2, name: 'hello world', reference_id: null },
  { id: 3, name: 'hello world', reference_id: null},
  { id: 4, name: 'hello world', reference_id: null },
  { id: 5, name: 'hello world', reference_id: 3 },
  { id: 6, name: 'hello world', reference_id: 2 },
];

const reorderedArray = test.reduce((acc, current) => {
      const referenceId = current.reference_id;
      if (referenceId === null) {
        const referencedChildIndex = acc.findIndex(item => item.reference_id === current.id);
        if (referencedChildIndex !== -1) {
          acc.splice(referencedChildIndex, 0, current);
        } else {
          acc.push(current);
        }
      } else {
        const referencedIndex = acc.findIndex(item => item.id === referenceId);
        if (referencedIndex !== -1) {
          acc.splice(referencedIndex + 1, 0, current);
        } else {
          acc.push(current);
        }
      }
      return acc;
    }, []);

console.log(reorderedArray);

My intuition tells me there should be a simpler code though, but today I'm tired :P

Kaddath
  • 5,933
  • 1
  • 9
  • 23
  • Hi I have updated the question with a new requirement but I am unable to find a solution can you help me by updating the answer – rasif sahl Jun 01 '23 at 00:29
  • You shouldn't edit a question in such a way that it invalids existing answers (since the edit, this answer no longer answers the question as it is stated), if you have following questions about adding another functionnality, you should ask a separate question. – Kaddath Jun 01 '23 at 07:42
0

Simpler approach: Group by the references and merge them in the required order.

  • Group all the items with respect to reference_id. Sample example would be:
{
  '2': [
    { id: 1, name: 'hello world', reference_id: 2 },
    { id: 6, name: 'hello world', reference_id: 2 }
  ],
  '3': [ { id: 5, name: 'hello world', reference_id: 3 } ]
}
  • Filter out the items that are not referenced. Sample example would be:
[ { id: 4, name: 'hello world', reference_id: null } ]

const data = [
    { id: 1, name: 'hello world', reference_id: 2 },
    { id: 2, name: 'hello world', reference_id: null },
    { id: 3, name: 'hello world', reference_id: null },
    { id: 4, name: 'hello world', reference_id: null },
    { id: 5, name: 'hello world', reference_id: 3 },
    { id: 6, name: 'hello world', reference_id: 2 },
]

// Group all the elements by reference_id
const grouping = {}
data.forEach(e => {
    if (e.reference_id) {
        if (e.reference_id in grouping) {
            grouping[e.reference_id] = [...grouping[e.reference_id], e];
        } else {
            grouping[e.reference_id] = [e];
        }
    }
});
 
const matches = []; // Contains element which are referenced 
const nullable = []; // Contains element which are not referenced (null) 

// Construct the matches and nullables
data.forEach(e => {
    if(e.id in grouping) {
        matches.push(e);
        matches.push(...grouping[e.id]);
    } else if(e.reference_id == null) {
        nullable.push(e);
    }
})

// Merge them to get desired result
const result = matches.concat(nullable);

console.log(result);
Shri Hari L
  • 4,551
  • 2
  • 6
  • 18
  • Hi I have updated the question can you check and update the answer because I couldn't find any solution for that either – rasif sahl Jun 01 '23 at 00:31