按值排列的紧凑型对象数组(Jquery 或下划线)

Compact Array of objects by value (Jquery or Underscore)

我有一个对象数组:

"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"
    } ]

我想把它改造成:

"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"
      } ]

我尝试首先在数组中使用唯一的 FieldName 值,然后在 JSON 数组中使用 _.filter 以尝试接收 return 中的数组,但所有我得到的是整个对象。

    $.each(arrUniqueFieldNames, function() {
        var strFName = String(this);
        oEntries[this] = _.filter(jsonEntries, function (item) { 
            if (item.FieldName === strFName) {
                return String(item.FieldValue) 
            } 
        });
    });

此代码中可能存在一些不完善之处,但它并没有像我预期的那样工作,因为它 return 是整个对象,而不仅仅是值。

我也尝试用 _.map 替换 _.filter,结果是我为每个数组得到了很多 "undefined".

我知道你想要 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);

另一个可能更好的 reusable/maintainable 解决方案,它也是纯粹基于语言核心的,可以使用 Array.prototype.reduce 然后可能看起来像那样 ...

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);
.as-console-wrapper { max-height: 100%!important; top: 0; }

附录/编辑

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

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);
.as-console-wrapper { max-height: 100%!important; top: 0; }