使嵌套在js中的平面对象

时间:2018-09-07 16:43:52

标签: javascript object

我想将我的对象转换为嵌套对象,以便能够在响应中递归地渲染输入(如果输入在此输入之下具有子输入渲染)有时输入顺序错误,所以我必须像这样转换对象/ p>

const start = {
  asdf: {
    id: "asdf",
    question: "How old are you?",
    type: "text"
  },
  "asdf/zxcv": {
    id: "asdf/zxcv",
    expect: 18,
    question: "Are you male?",
    type: "text"
  },
  "asdf/zxcv/yuio": {
    id: "asdf/zxcv/yuio",
    expect: "yes",
    question: "Do you like videogames?",
    type: "text"
  },
  "asdf/dfgh": {
    id: "asdf/dfgh",
    expect: 21,
    question: "Where do you live?",
    type: "text"
  },
  "asdf/dfgh/fghj": {
    id: "asdf/dfgh/fghj",
    expect: "Boston",
    question: "What's the weather?",
    type: "text"
  },
  qwer: {
    id: "qwer",
    question: "What is your name?",
    type: "text"
  },
  "qwer/asdf": {
    id: "qwer/asdf",
    expect: "David",
    question: "What is your surname",
    type: "text"
  }
};

变成这样

const result = {
  asdf: {
    id: "asdf",
    question: "How old are you?",
    type: "text",
    subs: [
      {
        id: "asdf/zxcv",
        expect: 18,
        question: "Are you male?",
        type: "text",
        subs: [
          {
            id: "asdf/zxcv/yuio",
            expect: "yes",
            question: "Do you like videogames?",
            type: "text"
          }
        ]
      },
      {
        id: "asdf/dfgh",
        expect: 21,
        question: "Where do you live?",
        type: "text",
        subs: [
          {
            id: "asdf/dfgh/fghj",
            expect: "Boston",
            question: "What's the weather?",
            type: "text"
          }
        ]
      }
    ]
  },
  qwer: {
    id: "qwer",
    question: "What is your name?",
    type: "text",
    subs: [
      {
        id: "qwer/asdf",
        expect: "David",
        question: "What is your surname",
        type: "text"
      }
    ]
  }
};

我可以创建对象的第一级,但是我不知道如何在需要时向潜艇动态添加对象

这是我的尝试。它不起作用。

const createObjToRender = object => {
  Object.values(object)
    .filter(o => o)
    .reduce((obj, el) => {
      const idHistory = el.id.split("/");

      if (idHistory.length > 1) {
        let elToAddSubInput = obj;

        for (let i = 0; i <= idHistory.length; i++) {
          i === 0 && (elToAddSubInput = elToAddSubInput[idHistory[i]]);
          i > 0 && (elToAddSubInput = elToAddSubInput.subs[idHistory[i]]);
        }

        elToAddSubInput.subs[idHistory.join("/")] = el;
      }

      if (idHistory.length === 1) {
        const id = idHistory[0];
        const { question, type } = el;
        if (!obj[id]) {
          obj[id] = {
            id,
            question,
            type,
            subs: {}
          };
        }
      }
    }, {});
};

1 个答案:

答案 0 :(得分:2)

您可以使用嵌套的哈希表快速构建树:

const start = {
  asdf: {
    id: "asdf",
    question: "How old are you?",
    type: "text"
  },
  "asdf/zxcv": {
    id: "asdf/zxcv",
    expect: 18,
    question: "Are you male?",
    type: "text"
  },
  "asdf/zxcv/yuio": {
    id: "asdf/zxcv/yuio",
    expect: "yes",
    question: "Do you like videogames?",
    type: "text"
  },
  "asdf/dfgh": {
    id: "asdf/dfgh",
    expect: 21,
    question: "Where do you live?",
    type: "text"
  },
  "asdf/dfgh/fghj": {
    id: "asdf/dfgh/fghj",
    expect: "Boston",
    question: "What's the weather?",
    type: "text"
  },
  qwer: {
    id: "qwer",
    question: "What is your name?",
    type: "text"
  },
  "qwer/asdf": {
    id: "qwer/asdf",
    expect: "David",
    question: "What is your surname",
    type: "text"
  }
};

// We use a symbol to allow fast lookups while still having a resulting array without it
const lookup = Symbol();
const root = { [lookup]: {}, sub: [] };

// As the ids are part of the values itself, we can ignore the objects keys and directly iterate the values
for(const el of Object.values(start)) {
  // Now we traverse down the nested lookup tree 
  let parent = root;
  for(const part of el.id.split("/")) {
    // If a certain path doesnt exist yet, set it up
    if(!parent[lookup][part]) 
      parent.sub.push(parent[lookup][part] = { [lookup]: {}, sub: [] });
    // Dive deeper
    parent = parent[lookup][part];
  }
  // We reached the node were the data belongs, so just assign it here:
  Object.assign(parent, el);
}

// you could also get it as an array with root.sub
console.log(root[lookup]);