访问对象中的数据并使用过滤后的数据创建新对象

时间:2017-03-18 03:13:57

标签: javascript lodash

我正在尝试搜索对象中的特定节点,并显示包含所需数据的新对象。每种复合类型中可能有单个或多个字段,如下所示。

这是原始对象:

{
  "section": "personal",
  "fields": [
    {
      "type": "composite",
      "name": "name",
      "label": "Name",
      "fields": [
        {
          "type": "text",
          "name": "given",
          "label": "First name",
          "value": "Joe"
        },
        {
          "type": "text",
          "name": "family",
          "label": "Last name",
          "value": "Smith"
        }
      ]
    },
    {
      "type": "composite",
      "name": "address",
      "label": "Address",
      "fields": [
        {
          "type": "text",
          "name": "streetName",
          "label": "Street Name",
          "value": "1 High St"
        },
        {
          "type": "text",
          "name": "city",
          "label": "City",
          "value": "New York"
        }
      ]
    }
  ]
}

生成的对象应如下所示:

{
  name: {
    given: "Joe",
    family: "Smith",
  },
  address: {
    streetName: "1 Hight St",
    city: "New York"
  }
}

编辑***理想情况下,我想找出一种方法来使用javascript方法(map / reduce / filter)和/或lodash来提出答案。

这更像是我目前使用内置方法所看到的内容。



var convertVals = function() {

  var data = fields.fields;
  var filter = data.filter(function(form) {
    return form
  })
  .filter(function(form) {
    return form.name && form.fields;
  })
  .map(function(form) {
    return {form.name, [form.name.name]: form.name.value};
  })
};
convertVals();




谢谢,

3 个答案:

答案 0 :(得分:1)

好的,你走吧!想象一下,我不妨对它进行抨击,因为没有更多的问题进入。

var originalObject = {
  "section": "personal",
  "fields": [
    {
      "type": "composite",
      "name": "name",
      "label": "Name",
      "fields": [
        {
          "type": "text",
          "name": "given",
          "label": "First name",
          "value": "Joe"
        },
        {
          "type": "text",
          "name": "family",
          "label": "Last name",
          "value": "Smith"
        }
      ]
    },
    {
      "type": "composite",
      "name": "address",
      "label": "Address",
      "fields": [
        {
          "type": "text",
          "name": "streetName",
          "label": "Street Name",
          "value": "1 High St"
        },
        {
          "type": "text",
          "name": "city",
          "label": "City",
          "value": "New York"
        }
      ]
    }
  ]
};

function convertVals(obj){
  var retObj = {};
  for(var i=0;i<obj.fields.length;i++){
    var tempObj={};
    for(var j=0;j<obj.fields[i].fields.length;j++){
      tempObj[obj.fields[i].fields[j].name] = obj.fields[i].fields[j].value;
    }
    retObj[obj.fields[i].name] = tempObj;
  }
  return retObj;
}

console.log(convertVals(originalObject));
/*
Should return:

{
  name: {
    given: "Joe",
    family: "Smith",
  },
  address: {
    streetName: "1 Hight St",
    city: "New York"
  }
}
*/

答案 1 :(得分:1)

这是一个使用keyBy为每个字段分配密钥的lodash解决方案,mapValues为每个字段获取值。

function getFields(data) {
  return data.value || _(data.fields)
    .keyBy('name')
    .mapValues(getFields)
    .value();
}

var data = {
  "section": "personal",
  "fields": [{
      "type": "composite",
      "name": "name",
      "label": "Name",
      "fields": [{
          "type": "text",
          "name": "given",
          "label": "First name",
          "value": "Joe"
        },
        {
          "type": "text",
          "name": "family",
          "label": "Last name",
          "value": "Smith"
        }
      ]
    },
    {
      "type": "composite",
      "name": "address",
      "label": "Address",
      "fields": [{
          "type": "text",
          "name": "streetName",
          "label": "Street Name",
          "value": "1 High St"
        },
        {
          "type": "text",
          "name": "city",
          "label": "City",
          "value": "New York"
        }
      ]
    }
  ]
};

function getFields(data) {
  return data.value || _(data.fields)
    .keyBy('name')
    .mapValues(getFields)
    .value();
}

console.log(getFields(data));
body > div { min-height: 100%; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

上述解决方案存在隐含的含义,如果value包含假值,则会忽略此value并假设有fields值。要解决此问题,我们可以使用has检查是否存在value密钥,然后执行与上面相同的操作。

function getFields(data) {
  return _.has(data, 'value')? data.value: 
    _(data.fields)
    .keyBy('name')
    .mapValues(getFields)
    .value();
}

var data = {
  "section": "personal",
  "fields": [{
      "type": "composite",
      "name": "name",
      "label": "Name",
      "fields": [{
          "type": "text",
          "name": "given",
          "label": "First name",
          "value": "Joe"
        },
        {
          "type": "text",
          "name": "family",
          "label": "Last name",
          "value": "Smith"
        }
      ]
    },
    {
      "type": "composite",
      "name": "address",
      "label": "Address",
      "fields": [{
          "type": "text",
          "name": "streetName",
          "label": "Street Name",
          "value": "1 High St"
        },
        {
          "type": "text",
          "name": "city",
          "label": "City",
          "value": "New York"
        }
      ]
    }
  ]
};

function getFields(data) {
  return _.has(data, 'value')? data.value: 
    _(data.fields)
    .keyBy('name')
    .mapValues(getFields)
    .value();
}

console.log(getFields(data));
body > div { min-height: 100%; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

答案 2 :(得分:1)

您可以使用Array.prototype.reduce()来迭代嵌套的fields数组。将父对象的"name"属性值设置为对象的属性名称,其值设置为对象设置为"name",并且"value"数组中的对象属性为"fields"

var data = {
  "section": "personal",
  "fields": [
    {
      "type": "composite",
      "name": "name",
      "label": "Name",
      "fields": [
        {
          "type": "text",
          "name": "given",
          "label": "First name",
          "value": "Joe"
        },
        {
          "type": "text",
          "name": "family",
          "label": "Last name",
          "value": "Smith"
        }
      ]
    },
    {
      "type": "composite",
      "name": "address",
      "label": "Address",
      "fields": [
        {
          "type": "text",
          "name": "streetName",
          "label": "Street Name",
          "value": "1 High St"
        },
        {
          "type": "text",
          "name": "city",
          "label": "City",
          "value": "New York"
        }
      ]
    }
  ]
}

var res = data.fields.reduce((o, {name, fields}) => 
           (o[name] = fields.reduce((curr, {name:key, value}) =>
             (curr[key] = value, curr),{}), o), {});

console.log(res);