0

I have a multidimentionnal array and i want to rename property recursevly, i've tried this function

const newMenu =
        Array.isArray(copyMenu) &&
        copyMenu.length > 0 &&
        copyMenu.map(({ families: children, id: key, label: title, ...rest }) => ({
            key,
            title,
            ...rest,
            children,
        }));

But it rename just the big array, not the properties inside table property This is my input array :

const input = [
{
    id: 9040,
    label: "33",
    tables: [
      {
        id: 8957,
        label: "THB_Adresse_Famille",
        idFather: 8957,
        tableIsFamily: false,
        tables: []
      },
      {
        id: 8941,
        label: "THB_Contact_Famille",
        idFather: 8941,
        tableIsFamily: false,
        tables: [
          { id: 8947, label: "THB_Contact_Table", idFather: 8941 },
          { id: 9855, label: "THB_Contact_Table_BIS", idFather: 8941 }
        ]
      },
      {
        id: 8949,
        label: "THB_Societe_Famille",
        idFather: 8949,
        tableIsFamily: false,
        tables: []
      },
      {
        id: 8983,
        label: "THB_TELEPHONE",
        idFather: 8983,
        tableIsFamily: false,
        tables: []
      },
      {
        id: 10070,
        label: "THB_TEST_5708",
        idFather: 10070,
        tableIsFamily: false,
        tables: []
      }
    ]
  },
   {
    id: 9761,
    label: "1111111",
    tables: [
      {
        id: 9742,
        label: "RRA PROTOCOLE",
        idFather: 9742,
        tableIsFamily: false,
        tables: []
      },
      {
        id: 9753,
        label: "RRA TEST CASE LINE",
        idFather: 9753,
        tableIsFamily: false,
        tables: []
      }
    ]
  },
]

The output should be ike this :

const output = [
{
    key: 9040,
    title: "33",
    children: [
      {
        key: 8957,
        title: "THB_Adresse_Famille",
        idFather: 8957,
        tableIsFamily: false,
        children: []
      },
      {
        key: 8941,
        title: "THB_Contact_Famille",
        idFather: 8941,
        tableIsFamily: false,
        children: [
          { key: 8947, title: "THB_Contact_Table", idFather: 8941 },
          { key: 9855, title: "THB_Contact_Table_BIS", idFather: 8941 }
        ]
      },
      {
        key: 8949,
        title: "THB_Societe_Famille",
        idFather: 8949,
        tableIsFamily: false,
        children: []
      },
      {
        key: 8983,
        title: "THB_TELEPHONE",
        idFather: 8983,
        tableIsFamily: false,
        children: []
      },
      {
        key: 10070,
        title: "THB_TEST_5708",
        idFather: 10070,
        tableIsFamily: false,
        children: []
      }
    ]
  },
 {
    key: 9761,
    title: "1111111",
    children: [
      {
        key: 9742,
        title: "RRA PROTOCOLE",
        idFather: 9742,
        tableIsFamily: false,
        children: []
      },
      {
        key: 9753,
        title: "RRA TEST CASE LINE",
        idFather: 9753,
        tableIsFamily: false,
        children: []
      }
    ]
  },
]

I'v searched on stackoverflow but i don't found any solutions to this case, any help will be appreciated. Thank you

1
  • So, at all levels, id becomes key, label becomes title and tables becomes children, correct? This may be a proper use-case for recursion. Will work on an answer. Commented Jan 31, 2022 at 10:13

4 Answers 4

2

You can use recursive approach to rename your keys by maintaining a lookup for renamed keys and recursively calling your function for array values.

const input = [ { id: 9040, label: "33", tables: [ { id: 8957, label: "THB_Adresse_Famille", idFather: 8957, tableIsFamily: false, tables: [] }, { id: 8941, label: "THB_Contact_Famille", idFather: 8941, tableIsFamily: false, tables: [ { id: 8947, label:"THB_Contact_Table", idFather: 8941 }, { id: 9855, label: "THB_Contact_Table_BIS", idFather: 8941 } ] }, { id: 8949, label: "THB_Societe_Famille", idFather: 8949, tableIsFamily: false, tables: [] }, { id: 8983, label: "THB_TELEPHONE", idFather: 8983, tableIsFamily: false, tables: [] }, { id: 10070, label: "THB_TEST_5708", idFather: 10070, tableIsFamily: false, tables: [] } ] }, { id: 9761, label: "1111111", tables: [ { id: 9742, label: "RRA PROTOCOLE", idFather: 9742, tableIsFamily: false, tables: [] }, { id: 9753, label: "RRA TEST CASE LINE", idFather: 9753, tableIsFamily: false, tables: [] } ] }, ],
    keys = { id: 'key', label: 'title', tables: 'children'},
    rename = (arr) => {
      return arr.map(o => {
        return Object.fromEntries(Object.keys(o).map(k => {
          const key = keys[k] || k;
          const value = Array.isArray(o[k]) ? rename(o[k]) : o[k];
          return [key, value];
        }));
      });
    };
console.log(rename(input));

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

Comments

1

I see your attempted solution is lacking the recursive call you say you want to implement. It may be a little tricky to conceive. You essentially need to wrap the repeating code in a function.

const recurse = (input) =>
  input?.map(({ tables, id, label, ...rest }) =>
    ({ children: recurse(tables), key: id, title: label, ...rest }))

Then, notice the function calls itself on the relevant part, a.k.a. the general case. Also not unimportantly, the function needs to know when to stop, i.e. when it has hit the base case. Without checking for the base case you will quickly find out where this website gets its name from. In the example above I did apply optional chaining so it is a bit subtle.

Edit: with regard to destructuring, there are roughly two equivalent approaches (as far as I can see), here is the other which matches more with your initial approach:

const recurse = (input) =>
  input?.map(({ tables, id: key, label: title, ...rest }) =>
    ({ children: recurse(tables), key, title, ...rest }))

Comments

0

Looks like a number of good answers have been provided. Here's one potential implementation to achieve the desired objective:

Sample Code

const replacePropsMap = {
  id: 'key',
  label: 'title',
  tables: 'children'
};

const renameProps = (arr = inputArr, propsMap = replacePropsMap) => (
  arr.reduce((fin, itm) => ([
    ...fin,
    {
      ...(
      Object.entries(itm).reduce((fin2, itm2) => ({
        ...fin2,
        ...(
          itm2[0] in propsMap
            ? { [propsMap[itm2[0]]]: itm2[1] }
            : {}
        )
      }), {})
      ),
      children: itm && itm.tables && itm.tables.length > 0
        ? renameProps(itm.tables)
        : []
    }
  ]), [])
);

Explanation

  • Use .reduce to iterate through the array (with the aggregator as fin and each item as itm)
  • Use ... spread-operator to first place existing items (from past iterations)
  • Next, for current itm, use Object.entries() and .reduce to filter-out id, label, tables props, but retain all other props
  • Use key, title to hold values of id, label respectively
  • Recurse the above for the tables array (if it exists) and store the result in children prop.

Code Snippet

const inputArr = [{
    id: 9040,
    label: "33",
    tables: [
      {
        id: 8957,
        label: "THB_Adresse_Famille",
        idFather: 8957,
        tableIsFamily: false,
        tables: []
      },
      {
        id: 8941,
        label: "THB_Contact_Famille",
        idFather: 8941,
        tableIsFamily: false,
        tables: [
          { id: 8947, label: "THB_Contact_Table", idFather: 8941 },
          { id: 9855, label: "THB_Contact_Table_BIS", idFather: 8941 }
        ]
      },
      {
        id: 8949,
        label: "THB_Societe_Famille",
        idFather: 8949,
        tableIsFamily: false,
        tables: []
      },
      {
        id: 8983,
        label: "THB_TELEPHONE",
        idFather: 8983,
        tableIsFamily: false,
        tables: []
      },
      {
        id: 10070,
        label: "THB_TEST_5708",
        idFather: 10070,
        tableIsFamily: false,
        tables: []
      }
    ]
  }, {
    id: 9761,
    label: "1111111",
    tables: [
      {
        id: 9742,
        label: "RRA PROTOCOLE",
        idFather: 9742,
        tableIsFamily: false,
        tables: []
      },
      {
        id: 9753,
        label: "RRA TEST CASE LINE",
        idFather: 9753,
        tableIsFamily: false,
        tables: []
      }
    ]
  }
];

const replacePropsMap = {
  id: 'key',
  label: 'title',
  tables: 'children'
};

const renameProps = (arr = inputArr) => (
    arr.reduce((fin, itm) => ([
    ...fin,
    {
        ...(
        Object.entries(itm).reduce((fin2, itm2) => ({
            ...fin2,
          ...(
            itm2[0] in replacePropsMap
                ? { [replacePropsMap[itm2[0]]]: itm2[1] }
              : {}
          )
        }), {})
      ),
      children: itm && itm.tables && itm.tables.length > 0
        ? renameProps(itm.tables)
        : []
    }
  ]), [])
);

console.log(renameProps());

Comments

-1

A potential solution could be:

const input = [{
    id: 9040,
    label: "33",
    tables: [{
        id: 8957,
        label: "THB_Adresse_Famille",
        idFather: 8957,
        tableIsFamily: false,
        tables: []
      },
      {
        id: 8941,
        label: "THB_Contact_Famille",
        idFather: 8941,
        tableIsFamily: false,
        tables: [{
            id: 8947,
            label: "THB_Contact_Table",
            idFather: 8941
          },
          {
            id: 9855,
            label: "THB_Contact_Table_BIS",
            idFather: 8941
          }
        ]
      },
      {
        id: 8949,
        label: "THB_Societe_Famille",
        idFather: 8949,
        tableIsFamily: false,
        tables: []
      },
      {
        id: 8983,
        label: "THB_TELEPHONE",
        idFather: 8983,
        tableIsFamily: false,
        tables: []
      },
      {
        id: 10070,
        label: "THB_TEST_5708",
        idFather: 10070,
        tableIsFamily: false,
        tables: []
      }
    ]
  },
  {
    id: 9761,
    label: "1111111",
    tables: [{
        id: 9742,
        label: "RRA PROTOCOLE",
        idFather: 9742,
        tableIsFamily: false,
        tables: []
      },
      {
        id: 9753,
        label: "RRA TEST CASE LINE",
        idFather: 9753,
        tableIsFamily: false,
        tables: []
      }
    ]
  },
];

function updateKeys(arr) {
  return arr.map(({
    tables,
    id: key,
    label: title,
    ...rest
  }) => {
    const children = Array.isArray(tables) && tables.length > 0 ? updateKeys(tables) : tables;
    return {
      key,
      title,
      children,
      ...rest
    }
  });
}

const output = updateKeys(input);

console.log(output);

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.