下面包含了从SQL数据库返回的数据集,因为除了一个属性"name_alt“之外,您可以看到所有数据都保持不变。
[{
"language_id": "tly",
"language_name": "Talysh",
"speakers_native": 800000,
"total_speakers": 912000,
"name_alt": "Taleshi",
"country_main": "az"
}, {
"language_id": "tly",
"language_name": "Talysh",
"speakers_native": 800000,
"total_speakers": 912000,
"name_alt": "Talish",
"country_main": "az"
}, {
"language_id": "tly",
"language_name": "Talysh",
"speakers_native": 800000,
"total_speakers": 912000,
"name_alt": "Talishi",
"country_main": "az"
}, {
"language_id": "tly",
"language_name": "Talysh",
"speakers_native": 800000,
"total_speakers": 912000,
"name_alt": "Talysh",
"country_main": "az"
}, {
"language_id": "tly",
"language_name": "Talysh",
"speakers_native": 800000,
"total_speakers": 912000,
"name_alt": "Talyshi",
"country_main": "az"
}, {
"language_id": "lez",
"language_name": "Lezghian",
"speakers_native": 171400,
"total_speakers": 428400,
"name_alt": "Kiurinsty",
"country_main": "ru"
}, {
"language_id": "lez",
"language_name": "Lezghian",
"speakers_native": 171400,
"total_speakers": 428400,
"name_alt": "Kiurinty",
"country_main": "ru"
}, {
"language_id": "lez",
"language_name": "Lezghian",
"speakers_native": 171400,
"total_speakers": 428400,
"name_alt": "Lezghi",
"country_main": "ru"
}]我希望将所有的name_alts组合成一个数组,所以我的数据如下所示:
[{
"language_id": "tly",
"language_name": "Talysh",
"speakers_native": 800000,
"total_speakers": 912000,
"name_alt": ["Talesh", "Taleshi", "Talish", "Talishi", "Talyshi"],
"country_main": "az"
}, {
"language_id": "lez",
"language_name": "Lezghian",
"speakers_native": 171400,
"total_speakers": 428400,
"name_alt": ["Kiurinsty", "Kiurinty", "Lezghi", "Lezgi", "Lezgian", "Lezgin"],
"country_main": "ru"
}]我编写了这个函数,它接受数组,映射并过滤它,以返回我需要的数据集。它很有效,但我担心它不是很好的表演。它接受我想要压缩的数组(array)、我想按其分组的属性(mappedProperty)、对每一行都应该保持唯一的属性(uniqueProperty),以及应该从分组属性集(mainProperty)中排除的属性。
你能复习一下吗?
function reduceRows(array, mappedProperty, uniqueProperty, mainProperty) {
var currentUniqueProp;
var objToReturn;
var mappedObj = _.map(array, function(obj) {
// we're grouping by the unique property (i.e. an ID), so if we have a new
// unique property, we clone the object, and start adding the
// mapped property (i.e. alternative names for a language) to the array
//usage: u.reduceRows(data.data.languages, "name_alt", "language_id", "language_name")
if (obj[uniqueProperty] != currentUniqueProp) {
objToReturn = _.clone(obj)
objToReturn[mappedProperty] = [obj[mappedProperty]]
currentUniqueProp = obj[uniqueProperty]
} else {
// sometimes the grouped property has a value which is the same as the main property
// i.e. the language_name is also included in the list of name_alts
// We want to avoid this duplication
if (obj[mappedProperty] != obj[mainProperty]) {
objToReturn[mappedProperty].push(obj[mappedProperty])
}
}
return objToReturn;
})
var filteredObj = _.filter(mappedObj, function(obj) {
//this function ensures that only one entry for each unique property
//is returned
if (obj[uniqueProperty] == currentUniqueProp) {
return false
} else {
currentUniqueProp = obj[uniqueProperty]
return true
}
})
return filteredObj
}发布于 2014-11-05 15:32:20
有几件事:
Array.prototype.map和Array.prototype.filter。将_.map(array, function)替换为array.map(function)等。(anonymous function)。map用于将一个数组映射到另一个数组,如果您只想迭代一个数组并运行一个函数,则需要Array.prototype.forEach。我会采取另一种方法来做这件事。
reduce分别迭代到单个对象。以下是我的看法:
// ## Get an array of language_ids to be used as a unique key.
// ## I'm assuming here that if language_id is equal, the rest (aside from name_alt) is also equal.
var uniqueKeys = data
.map(function pluckLanguageId(obj) { return obj.language_id; })
//Now your array looks like ["a", "a", "a", "b", "b" ,"b"]
.filter(function makeUnique(language, index, array) { return array.indexOf(language) === index; });
//Now your array looks like ["a", "b"]
// ## Map each of the keys to a formatted object:
var result = uniqueKeys.map(function mapKeysToFormattedObjects(key) {
//Take the entire data array
return data
//Filter it by language_id
.filter(function getOnlyDataWithKey(item) { return item.language_id === key; })
//Then combine it into one object
.reduce(function combineToOneObject(previous, current) {
if (typeof(previous.name_alt) === "string") { //In this first object, the name_alt would be a string.
previous.name_alt = [previous.name_alt]; //So make it into an array!
}
previous.name_alt.push(current.name_alt); //Push the current name_alt into the previous one.
return previous;
}); //Result is an object with all of the name_alts in an array
})这是假设原始数据在data变量中。如果有什么你不明白的,请告诉我,我会尽力解释的。
注意我是如何链接我的调用映射,过滤和减少。map和filter都返回一个数组,因此对这个新处理的数组执行链式调用。
一种更理想的编写方法是将所有的东西分解成函数,然后有一个oneliner:
function pluckLanguageId(obj) { return obj.language_id; }
function makeUnique(language, index, array) { return array.indexOf(language) === index; }
function mapKeysToFormattedObjects(key) {
return data
.filter(function getOnlyDataWithKey(item) { return item.language_id === key; })
.reduce(function combineToOneObject(previous, current) {
if (typeof(previous.name_alt) === "string") { //In this first object, the name_alt would be a string.
previous.name_alt = [previous.name_alt]; //So make it into an array!
}
previous.name_alt.push(current.name_alt); //Push the current name_alt into the previous one.
return previous;
}); //Result is an object with all of the name_alts in an array
}
var result = data.map(pluckLanguageId).filter(makeUnique).map(mapKeysToFormattedObjects);
//One liner!这段代码可以通过返回函数和诸如此类的函数来进一步改进,但是以第一个例子作为参考。
发布于 2014-11-05 14:17:23
因为javascript有一个else if语句,所以您应该使用它来删除一个级别的缩进。
if (obj[uniqueProperty] != currentUniqueProp) {
objToReturn = _.clone(obj)
objToReturn[mappedProperty] = [obj[mappedProperty]]
currentUniqueProp = obj[uniqueProperty]
} else if (obj[mappedProperty] != obj[mainProperty]) {
// sometimes the grouped property has a value which is the same as the main property
// i.e. the language_name is also included in the list of name_alts
// We want to avoid this duplication
objToReturn[mappedProperty].push(obj[mappedProperty])
} underscore滤波方法可以简化为
var filteredObj = _.filter(mappedObj, function(obj) {
//this function ensures that only one entry for each unique property
//is returned
if (obj[uniqueProperty] == currentUniqueProp) {
return false
}
currentUniqueProp = obj[uniqueProperty]
return true
})如果条件的计算结果为true,则方法将返回,因此不需要else。
您应该始终在需要变量的地方声明它们。所以var objToReturn应该在这里声明
var mappedObj = _.map(array, function(obj) {
var objToReturn;
// we're grouping by the unique property https://codereview.stackexchange.com/questions/68964
复制相似问题