创建具有所需树结构的对象

时间:2018-11-23 09:31:23

标签: javascript

我一直试图创建一个树结构,如下:

var result = {
  email: {
    schema: {
      verified: 'email.verified',
      email_address: 'email.email_address',
      entity: {
        schema: {
          name: 'email.entity.name',
          type: 'email.entity.type',
          email: {
            schema: {
              verified: 'email.entity.email.verified',
              email_address: 'email.entity.email.email_address'
            }
          }
        }
      }
    }
  }
};

根据下面给出的数组数据:

var schema = {
  'paths': [
    'email.email_address',
    'email.entity.email.email_address',
    'email.entity.email.verified',
    'email.entity.type',
    'email.entity.name',
    'email.verified',
    'created_at',
    'contact_numbers'
  ]
}

您看到我期望的输出具有schema级嵌套的n属性,这是不可预测的。就像paths一样,它取决于'email.entity.email.email_address'的值。您可以用点将其拆分,并且看起来每个点在输出中都被schema属性替换。

我正在尝试使用递归,但是我无法设置该流程。下面是到目前为止我尝试过的代码:

var schema = {
  'paths': [
    'email.email_address',
    'email.entity.email.email_address',
    'email.entity.email.verified',
    'email.entity.type',
    'email.entity.name',
    'email.verified',
    'created_at',
    'contact_numbers'
  ]
}
var newSchema = {};

var key = 'email';
var existKeys = schema.paths.filter((path) => path.includes(key + '.'));
var requiredObject = {};
existKeys.forEach((existKey) => {
  var splitKeys = existKey.split('.');
  splitKeys.forEach((splitKey, index) => {
    if (requiredObject[splitKey] && index + 1 === splitKeys.length) {
      requiredObject[splitKey].schema = existKey;
    } else {
      requiredObject[splitKey] = {
        'schema': {}
      }
    }
  });
});
console.log(requiredObject);

3 个答案:

答案 0 :(得分:1)

您可以减少路径,并为每个找到的键都设置一个schema属性。

var schema = { paths: ['email.email_address', 'email.entity.email.email_address', 'email.entity.email.verified', 'email.entity.type', 'email.entity.name', 'email.verified', 'created_at', 'contact_numbers'] },
    result = schema.paths
        .filter(s => s.startsWith('email')) // or not or so, if so, maybe
        .reduce((r, p) => {
            var keys = p.split('.'),
                last = keys.pop();

            keys.reduce((o, k) => (o[k] = o[k] || { schema: {} }).schema, r)[last] = p;
            return r;
        }, {});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 1 :(得分:0)

我使用辅助函数reducepaths数组上assignNested,给定一个外部对象,一个值和一个属性数组,该函数使用top属性创建schema对象并递归调用自身,直到数组只剩下一项,并且可以分配最终值:

var schema = {
  'paths': [
    'email.email_address',
    'email.entity.email.email_address',
    'email.entity.email.verified',
    'email.entity.type',
    'email.entity.name',
    'email.verified',
    'created_at',
    'contact_numbers'
  ]
};

function assignNested(obj, val, props) {
  if (props.length === 1) {
    obj[props[0]] = val;
    return;
  }
  const nextProp = props.shift();
  if (!obj.schema) obj.schema = {};
  if (!obj.schema[nextProp]) obj.schema[nextProp] = {};
  assignNested(obj.schema[nextProp], val, props);
}

const fullResult = schema.paths.reduce((a, path) => {
  const props = path.split('.');
  assignNested(a, path, props);
  return a;
}, {});

// fullResult contains the *full* structure,
// but if you only want the nested `email` part, then:
const result = {
  email: {
    schema: fullResult.schema.email
  }
};
console.log(result);

答案 2 :(得分:0)

使用2 Array.reduce可以实现以下效果

var schema = {
  'paths': [
    'email.email_address',
    'email.entity.email.email_address',
    'email.entity.email.verified',
    'email.entity.type',
    'email.entity.name',
    'email.verified',
    'created_at',
    'contact_numbers'
  ]
}

let res = schema.paths.reduce((o, d) => {
  let keys = d.split('.')
  keys.reduce((t, k, i) => {
    t[k] = (i != keys.length - 1)
              ? (t[k] || { schema: {} })
              : d

    return t[k].schema
  }, o)
  
  return o
}, {})

console.log(res)

// for only email
console.log({ email: res.email })