skip to Main Content

This is the array what I am getting

[
  { 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 },
]

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

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

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 as an example

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

This is the code that I tried

var product={product_skus:
[
  { 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 = product?.product_skus.reduce((acc, current) => {
      const referenceId = current.reference_id;
      if (referenceId === null) {
        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.

2

Answers


  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 😛

    Login or Signup to reply.
  2. 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);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search