繁体   English   中英

分组并聚合一组javascript对象

[英]Group and aggregate an array of javascript objects

我在合理化和聚合javascript中的对象数组时遇到了一些麻烦。

给定数组

[{"description":"Bright","size":"2XL","price":10.99},{"description":"Bright","size":"XL","price":10.99},{"description":"Bright","size":"L","price":9.99},{"group":"Foos","description":"Dull","size":"XL","price":9.99},{"description":"Dull","size":"L","price":8.99},{"description":"Dull","size":"2XL","price":9.99},{"description":"Shiny","size":"XL","price":9.99},{"description":"Shiny","size":"S","price":8.99},{"description":"Shiny","size":"3XL","price":10.3},{"description":"Shiny","size":"2XL","price":9.99}]

我正在尝试将其转换为格式的数组(此处的实际值可能是错误的)。

[{"descriptions":"Shiny, Bright, Dull","sizeRange":"S - L","price":8.99},{"descriptions":"Shiny, Bright, Dull","sizes":"XL - 2XL","price":9.99},{"descriptions":"Dark","sizes":"S - 2XL","price":10.99}]

即-我希望按价格对每组商品进行分组,显示它们的描述和尺寸范围。

到目前为止,这是我所拥有的,并且似乎正在运行,但是看起来非常麻烦。 如果能稍微合理化代码而不是使用本机JS,我真的很乐意使用lodash或下划线之类的东西。

function groupBy (array, key) {
  return array.reduce(function(value, property) {
    (value[property[key]] = value[property[key]] || []).push(property);
    return value;
  }, {});
};

function unique(array) {
  return Array.from(new Set(array));
};

function getRanges(data)
{
    var result = [];

    // simple map of sizes from smallest to largest to use for sorting
    var sizeSort = {'S':1, 'M':2, 'L':3, 'XL':4, '2XL':5, '3XL':6, '4XL':7, '5XL':8};

    // group the remaining variants by price
    var group = groupBy(data, 'price');

    // for each variant price group 
    for(var price in group) {
        var item = {};
        item.price = price;
        // get the range of sizes sorted smallest to largest
        var sizes = unique(group[price].map(function(i) {
            return i.size;
        })).sort(function(a, b) {
            return sizeSort[a] - sizeSort[b];
        });

        // Add single size, or first and last size.
        item.sizes = (sizes.length === 1) ?
           sizes.shift() :
           sizes.shift() + ' - ' + sizes.pop();

        // Add the descriptions as alphabetically sorted CSV
        item.description = unique(group[price].map(function(i) {
            return i.description;
        })).sort().join(", ");

        result.push(item);
    }

    return result;
}

这是使用lodash的版本。我认为它看起来更合理。

 function calc(data) { var sizeSort = {'S':1, 'M':2, 'L':3, 'XL':4, '2XL':5, '3XL':6, '4XL':7, '5XL':8}; return _.chain(data). groupBy('price'). map(function(f){ var sizes = _.chain(f).map('size').uniq(). sortBy(function (a) { return sizeSort[a] }).value(); return { price: _.head(f).price, description: _.chain(f).map('description').uniq().join(',').value(), size: sizes.length === 1 ? _.first(sizes) : _.join([_.first(sizes),_.last(sizes)], ' - ') } }). sortBy(['price']). value(); } //put data at end, so not having to scroll down to see code var data = [{"description":"Bright","size":"2XL","price":10.99},{"description":"Bright","size":"XL","price":10.99},{"description":"Bright","size":"L","price":9.99},{"group":"Foos","description":"Dull","size":"XL","price":9.99},{"description":"Dull","size":"L","price":8.99},{"description":"Dull","size":"2XL","price":9.99},{"description":"Shiny","size":"XL","price":9.99},{"description":"Shiny","size":"S","price":8.99},{"description":"Shiny","size":"3XL","price":10.3},{"description":"Shiny","size":"2XL","price":9.99}]; console.log(calc(data)); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.3/lodash.js"></script> 

原始的JavaScript解决方案(带有ES6模板字符串)

/*
  Some boilerplate functions. Listed underscore/lodash functions that 
  could replace them above
*/

// _.mapObject(object, reducer)
function reduceValues(object, reducer) {
  let newObject = {}
    for (var property in object) {
      if (object.hasOwnProperty(property)) {
          newObject[property] = reducer(object[property])
      }
    }
  return newObject
}

// _.groupBy
function groupBy(arr, key) {
  let reducer = (grouped, item) => {
    let group_value = item[key]
    if (!grouped[group_value]) {
      grouped[group_value] = []
    }
    grouped[group_value].push(item)
    return grouped
  }
  return arr.reduce(reducer, {})
}

// _.values
function objectValues(object) {
  let values = []
  for (var property in object) {
    if (object.hasOwnProperty(property)) {
        values.push(object[property])
    }
  }
  return values
}

/*
  Shirt specific functions and data
*/

// Mapping of shirts to their order.
let sizesToNumbers = {'S':1, 'M':2, 'L':3, 'XL':4, '2XL':5, '3XL':6, '4XL':7, '5XL':8};

// Create an intermediate summary with data instead of strings.
// This makes processing easier to write and reason about
function reduceShirtsToSummary(shirts) {
  let reducer = (summary, shirt) => {
    summary['descriptions'].add(shirt['description'])
    let shirtSize = shirt['size']
    if (!summary['smallestSize'] || sizesToNumbers[shirtSize] < sizesToNumbers[summary['smallestSize']]) {
      summary['smallestSize'] = shirtSize
    }
    if (!summary['largestSize'] || sizesToNumbers[shirtSize] > sizesToNumbers[summary['largestSize']]) {
      summary['largestSize'] = shirtSize
    }
    summary['prices'].push(shirt['price'])
    return summary
  }
  return shirts.reduce(reducer, {'descriptions': new Set(), 'prices': []})
}

// Convert the shirt summary data into the "labelized" version with strings in the example
function labelizeShirtSummary(shirtSummary) {
  let labelizedShirtSummary = {}
  labelizedShirtSummary['descriptions'] = Array.from(shirtSummary['descriptions']).join(', ')
  labelizedShirtSummary['price'] = shirtSummary['prices'][0]
  labelizedShirtSummary['sizes'] = `${shirtSummary['smallestSize']} - ${shirtSummary['largestSize']}`
  return labelizedShirtSummary
}

let grouped = groupBy(shirts, 'price')
let groupedAndSummarized = reduceValues(grouped, reduceShirtsToSummary)
let labelizedSummaries = objectValues(groupedAndSummarized).map(labelizeShirtSummary)
// Gives desired output
console.log(labelizedSummaries)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM