按值的紧凑对象数组(Jquery或Underscore)

时间:2018-01-10 14:50:46

标签: javascript arrays data-structures mapreduce underscore.js

我有一个对象数组:

<a>

我想将其转换为:

"Entries" : [ {
        "FieldName" : "Name1",
        "FieldValue" : "N1Value1"
    }, {
        "FieldName" : "Name1",
        "FieldValue" : "N1Value2"
    }, {
        "FieldName" : "Name1",
        "FieldValue" : "N1Value3"
    }, {
        "FieldName" : "Name2",
        "FieldValue" : "N2Value1"
    }, {
        "FieldName" : "Name2",
        "FieldValue" : "N2Value2"
    }, {
        "FieldName" : "Name2",
        "FieldValue" : "N2Value3"
    }, {
        "FieldName" : "Name3",
        "FieldValue" : "N3Value1"
    }, {
        "FieldName" : "Name4",
        "FieldValue" : "N4Value1"
    }, {
        "FieldName" : "Name5",
        "FieldValue" : "N5Value1"
    } ]

我试图在数组中首先使用唯一的FieldName值,然后在JSON数组中使用_.filter尝试接收数组作为回报,但我得到的只是整个对象。

"Entries" : [ {
          "FieldName" : "Name1",
          "FieldValue" : ["N1Value1","N1Value2","N1Value3"] 
      }, {
          "FieldName" : "Name2",
          "FieldValue" : ["N2Value1", "N2Value2", "N2Value3"]
      }, {
          "FieldName" : "Name3",
          "FieldValue" : "N3Value1"
      }, {
          "FieldName" : "Name4",
          "FieldValue" : "N4Value1"
      }, {
          "FieldName" : "Name5",
          "FieldValue" : "N5Value1"
      } ]

这段代码中可能没有什么不完美之处,但它并没有像我期望的那样工作,因为它返回整个对象而不仅仅是值。

我还试图将_.filter替换为_.map,但结果是每个数组都有很多&#34; undefined&#34;。

2 个答案:

答案 0 :(得分:-1)

我知道你想用jquery,但我不是那么坚定所以我给你一个纯JavaScript的解决方案:

test =  [ {
    "FieldName" : "Name1",
    "FieldValue" : "N1Value1"
    }, {
    "FieldName" : "Name1",
    "FieldValue" : "N1Value2"
    }, {
    "FieldName" : "Name1",
    "FieldValue" : "N1Value3"
    }, {
    "FieldName" : "Name2",
    "FieldValue" : "N2Value1"
    }, {
    "FieldName" : "Name2",
    "FieldValue" : "N2Value2"
    }, {
    "FieldName" : "Name2",
    "FieldValue" : "N2Value3"
    }, {
    "FieldName" : "Name3",
    "FieldValue" : "N3Value1"
    }, {
    "FieldName" : "Name4",
    "FieldValue" : "N4Value1"
    }, {
    "FieldName" : "Name5",
    "FieldValue" : "N5Value1"
    } ];

result =[];

for (i=0; i<test.length; i++)
{
    element=test[i];
    key=element['FieldName'];
    value=element['FieldValue'];
    if (!(key in result))
        result[key] = [value];
    else
        result[key].push(value);
}
console.log(result);

答案 1 :(得分:-1)

另一个可能更好的可重复使用/可维护的解决方案,也是基于语言核心的解决方案,可以使用Array.prototype.reduce然后看起来像......

&#13;
&#13;
var entries = [{
  "FieldName" : "Name1",
  "FieldValue": "N1Value1"
}, {
  "FieldName" : "Name1",
  "FieldValue": "N1Value2"
}, {
  "FieldName" : "Name1",
  "FieldValue": "N1Value3"
}, {
  "FieldName" : "Name2",
  "FieldValue": "N2Value1"
}, {
  "FieldName" : "Name2",
  "FieldValue": "N2Value2"
}, {
  "FieldName" : "Name2",
  "FieldValue": "N2Value3"
}, {
  "FieldName" : "Name3",
  "FieldValue": "N3Value1"
}, {
  "FieldName" : "Name4",
  "FieldValue": "N4Value1"
}, {
  "FieldName" : "Name5",
  "FieldValue": "N5Value1"
}];


function collectAndGroupValuesOfEquallyNamedFieldItems (collector, fieldItem) {
  var
    fieldName = fieldItem.FieldName,
    itemGroup = collector.map[fieldName];

  if (!itemGroup) {
    itemGroup  = collector.map[fieldName] = {

      "FieldName" : fieldName,
      "FieldValue": []
    };
    collector.list.push(itemGroup);
  }
  itemGroup.FieldValue.push(fieldItem.FieldValue);

  return collector;
}


entries = entries.reduce(collectAndGroupValuesOfEquallyNamedFieldItems, {

  map:  {},
  list: []

}).list;


console.log('entries : ', entries);
&#13;
.as-console-wrapper { max-height: 100%!important; top: 0; }
&#13;
&#13;
&#13;

附录/编辑

@Paprika ...考虑到@rockstar的最后评论,上述解决方案可识别FieldValue的双重数据结构 - {String}单个值FieldValue多个{Array<String>}值的值和FieldValue - 确实更改为...

&#13;
&#13;
var entries = [{
  "FieldName" : "Name1",
  "FieldValue": "N1Value1"
}, {
  "FieldName" : "Name1",
  "FieldValue": "N1Value2"
}, {
  "FieldName" : "Name1",
  "FieldValue": "N1Value3"
}, {
  "FieldName" : "Name2",
  "FieldValue": "N2Value1"
}, {
  "FieldName" : "Name2",
  "FieldValue": "N2Value2"
}, {
  "FieldName" : "Name2",
  "FieldValue": "N2Value3"
}, {
  "FieldName" : "Name3",
  "FieldValue": "N3Value1"
}, {
  "FieldName" : "Name4",
  "FieldValue": "N4Value1"
}, {
  "FieldName" : "Name5",
  "FieldValue": "N5Value1"
}];


function collectAndGroupValuesOfEquallyNamedFieldItems (collector, fieldItem) {
  var
    fieldName = fieldItem.FieldName,
    itemGroup = collector.map[fieldName];

  if (!itemGroup) {
    itemGroup  = collector.map[fieldName] = {

      "FieldName" : fieldName,
      "FieldValue": null
    };
    collector.list.push(itemGroup);
  }
  if (Array.isArray(itemGroup.FieldValue)) { // list/array of multiple string values.

    itemGroup.FieldValue.push(fieldItem.FieldValue);

  } else if (typeof itemGroup.FieldValue === 'string') { // data structure switch.

    itemGroup.FieldValue = [itemGroup.FieldValue, fieldItem.FieldValue]

  } else if (itemGroup.FieldValue === null) { // initial string value.

    itemGroup.FieldValue = fieldItem.FieldValue;
  }
  return collector;
}


entries = entries.reduce(collectAndGroupValuesOfEquallyNamedFieldItems, {

  map:  {},
  list: []

}).list;


console.log('entries : ', entries);
&#13;
.as-console-wrapper { max-height: 100%!important; top: 0; }
&#13;
&#13;
&#13;