如何根据包含的 属性 的第一个字母过滤数组?
How can I filter an array based on the first letter of a contained property?
我有以下 JavaScript 个对象数组:
[{name: '4 Arn', isLetter: false},
{name: 'Abax', isLetter: false},
{name: 'Aramex', isLetter: false},
{name: 'Booking', isLetter: false},
{name: 'Dangerous', isLetter: false},
{name: 'Manali', isLetter: false}]
在上面的数组中,我想检查每个项目的第一个字母 name
属性。如果匹配,我想在对象之前附加一个新对象,如下例所示:
[{letter: "#", isLetter: true}, // new object
{name: '4 Arn', isLetter: false},
{letter: "A", isLetter: true}, // new Object
{name: 'Abax', isLetter: false},
{name: 'Aramex', isLetter: false},
{letter: "B", isLetter: true}, // new object
{name: 'Booking', isLetter: false},
{letter: "D", isLetter: true}, // new object
{name: 'Dangerous', isLetter: false},
{letter: "M", isLetter: true}, // new object
{name: 'Manali', isLetter: false}]
我尝试了 reduce()
函数,但我不明白为什么它会给我错误的结果:
var newArr = [];
list.reduce(function(prev, cur, index, originalArrray) {
var previousCharcode = prev.name.toUpperCase().charCodeAt(0);
currentCharCode = cur.name.toUpperCase().charCodeAt(0);
newArr.push(prev);
if(previousCharcode != currentCharCode) {
newArr.splice(index, 0, {isLetter: true, letter: String.fromCharCode(currentCharCode)});
}
return cur;
});
检查这个解决方案。迭代数组并将其附加到新数组。
var names = [{
name: '4 Arn',
isLetter: false
}, {
name: 'Abax',
isLetter: false
}, {
name: 'Aramex',
isLetter: false
}, {
name: 'Booking',
isLetter: false
}, {
name: 'Dangerous',
isLetter: false
}, {
name: 'Manali',
isLetter: false
}];
var newNames = [];
for (var i in names) {
var char = names[i].name.substring(0, 1);
var isNumber = !isNaN(char);
var entry = {
letter: (isNumber ? '#' : char.toUpperCase()),
isLetter: isNumber
};
newNames.push(entry);
newNames.push(names[i]);
}
console.log(newNames);
也许用这种方法可以解决问题
var list = [{name: '4 Arn', isLetter: false},
{name: 'Abax', isLetter: false},
{name: 'Aramex', isLetter: false},
{name: 'Booking', isLetter: false},
{name: 'Dangerous', isLetter: false},
{name: 'Manali', isLetter: false}];
var listResult = [];
list.map(function(item, index) {
if(index > 0) {
var currentCharcode = item.name.toUpperCase().charCodeAt(0);
var previousCharcode = list[index-1].name.toUpperCase().charCodeAt(0);
if(previousCharcode != currentCharcode) {
listResult.push({isLetter: true, letter: String.fromCharCode(currentCharcode)});
}
} else {
listResult.push({isLetter: true, letter: String.fromCharCode(currentCharcode)});
}
listResult.push(item);
});
console.log(JSON.stringify(listResult));
我想你也可以像这样用函数式的方式做;
var arr = [{name: '4 Arn', isLetter: false},
{name: 'Abax', isLetter: false},
{name: 'Aramex', isLetter: false},
{name: 'Booking', isLetter: false},
{name: 'Dangerous', isLetter: false},
{name: 'Manali', isLetter: false}],
table = arr.reduce((p,c) => {var firstLetter = c.name[0];
isNaN(+firstLetter) ? p[firstLetter] ? p[firstLetter].push(c)
: p[firstLetter] = [c]
: p["#"] ? p["#"].push(c)
: p["#"] = [c];
return p;
},{}),
result = Object.keys(table).reduce((p,k) => p.concat({letter: k, isLetter: true},table[k]),[]);
console.log(result);
提示:+"A" returns NaN 但 +"4" returns 4 作为数字。所以isNaN()
是一个非常有用的函数来检查类型。
这里是没有箭头的常规功能版本;
var arr = [{name: '4 Arn', isLetter: false},
{name: 'Abax', isLetter: false},
{name: 'Aramex', isLetter: false},
{name: 'Booking', isLetter: false},
{name: 'Dangerous', isLetter: false},
{name: 'Manali', isLetter: false}],
table = arr.reduce(function(p,c){
var firstLetter = c.name[0];
isNaN(+firstLetter) ? p[firstLetter] ? p[firstLetter].push(c)
: p[firstLetter] = [c]
: p["#"] ? p["#"].push(c)
: p["#"] = [c];
return p;
},{}),
result = Object.keys(table).reduce(function(p,k){
return p.concat({letter: k, isLetter: true},table[k]);
},[]);
console.log(result);
至少有两个原因导致您的代码没有给出预期的结果:
您使用的索引指向原始数组中的索引。由于您的新数组将包含更多元素,因此将该索引用于新数组上的 splice
是没有意义的。它最终会指向错误的地方;
你只压入prev
元素,所以最后一个元素永远不会被压入结果数组
我建议使用 reduce
和一个累加值(回调的第一个参数)来构建最终数组。为了记住介绍的最后一个字母对象,我将把这个累积值与那个字母配对。所以我将使用包含两个元素的数组:
- 正在累积的最终数组
- 最近添加的字母对象的字母
那么最终结果将从该数组的第一个元素中获取,忽略第二个值。
我建议不要使用字符代码,而只使用字符。它使您免于将代码转换回字符。
代码如下:
var list = [
{name: '4 Arn', isLetter: false},
{name: 'Abax', isLetter: false},
{name: 'Aramex', isLetter: false},
{name: 'Booking', isLetter: false},
{name: 'Dangerous', isLetter: false},
{name: 'Manali', isLetter: false}
];
var newArr = list.reduce(function(collect, cur, index, originalArrray) {
var currentChar = cur.name.toUpperCase().substr(0,1);
if (currentChar < 'A') currentChar = '#';
if (collect[1] != currentChar) {
collect[0].push({isLetter: true, letter: currentChar});
collect[1] = currentChar;
}
collect[0].push(cur);
return collect;
}, [[], null])[0];
// output
console.log(newArr);
我有以下 JavaScript 个对象数组:
[{name: '4 Arn', isLetter: false},
{name: 'Abax', isLetter: false},
{name: 'Aramex', isLetter: false},
{name: 'Booking', isLetter: false},
{name: 'Dangerous', isLetter: false},
{name: 'Manali', isLetter: false}]
在上面的数组中,我想检查每个项目的第一个字母 name
属性。如果匹配,我想在对象之前附加一个新对象,如下例所示:
[{letter: "#", isLetter: true}, // new object
{name: '4 Arn', isLetter: false},
{letter: "A", isLetter: true}, // new Object
{name: 'Abax', isLetter: false},
{name: 'Aramex', isLetter: false},
{letter: "B", isLetter: true}, // new object
{name: 'Booking', isLetter: false},
{letter: "D", isLetter: true}, // new object
{name: 'Dangerous', isLetter: false},
{letter: "M", isLetter: true}, // new object
{name: 'Manali', isLetter: false}]
我尝试了 reduce()
函数,但我不明白为什么它会给我错误的结果:
var newArr = [];
list.reduce(function(prev, cur, index, originalArrray) {
var previousCharcode = prev.name.toUpperCase().charCodeAt(0);
currentCharCode = cur.name.toUpperCase().charCodeAt(0);
newArr.push(prev);
if(previousCharcode != currentCharCode) {
newArr.splice(index, 0, {isLetter: true, letter: String.fromCharCode(currentCharCode)});
}
return cur;
});
检查这个解决方案。迭代数组并将其附加到新数组。
var names = [{
name: '4 Arn',
isLetter: false
}, {
name: 'Abax',
isLetter: false
}, {
name: 'Aramex',
isLetter: false
}, {
name: 'Booking',
isLetter: false
}, {
name: 'Dangerous',
isLetter: false
}, {
name: 'Manali',
isLetter: false
}];
var newNames = [];
for (var i in names) {
var char = names[i].name.substring(0, 1);
var isNumber = !isNaN(char);
var entry = {
letter: (isNumber ? '#' : char.toUpperCase()),
isLetter: isNumber
};
newNames.push(entry);
newNames.push(names[i]);
}
console.log(newNames);
也许用这种方法可以解决问题
var list = [{name: '4 Arn', isLetter: false},
{name: 'Abax', isLetter: false},
{name: 'Aramex', isLetter: false},
{name: 'Booking', isLetter: false},
{name: 'Dangerous', isLetter: false},
{name: 'Manali', isLetter: false}];
var listResult = [];
list.map(function(item, index) {
if(index > 0) {
var currentCharcode = item.name.toUpperCase().charCodeAt(0);
var previousCharcode = list[index-1].name.toUpperCase().charCodeAt(0);
if(previousCharcode != currentCharcode) {
listResult.push({isLetter: true, letter: String.fromCharCode(currentCharcode)});
}
} else {
listResult.push({isLetter: true, letter: String.fromCharCode(currentCharcode)});
}
listResult.push(item);
});
console.log(JSON.stringify(listResult));
我想你也可以像这样用函数式的方式做;
var arr = [{name: '4 Arn', isLetter: false},
{name: 'Abax', isLetter: false},
{name: 'Aramex', isLetter: false},
{name: 'Booking', isLetter: false},
{name: 'Dangerous', isLetter: false},
{name: 'Manali', isLetter: false}],
table = arr.reduce((p,c) => {var firstLetter = c.name[0];
isNaN(+firstLetter) ? p[firstLetter] ? p[firstLetter].push(c)
: p[firstLetter] = [c]
: p["#"] ? p["#"].push(c)
: p["#"] = [c];
return p;
},{}),
result = Object.keys(table).reduce((p,k) => p.concat({letter: k, isLetter: true},table[k]),[]);
console.log(result);
提示:+"A" returns NaN 但 +"4" returns 4 作为数字。所以isNaN()
是一个非常有用的函数来检查类型。
这里是没有箭头的常规功能版本;
var arr = [{name: '4 Arn', isLetter: false},
{name: 'Abax', isLetter: false},
{name: 'Aramex', isLetter: false},
{name: 'Booking', isLetter: false},
{name: 'Dangerous', isLetter: false},
{name: 'Manali', isLetter: false}],
table = arr.reduce(function(p,c){
var firstLetter = c.name[0];
isNaN(+firstLetter) ? p[firstLetter] ? p[firstLetter].push(c)
: p[firstLetter] = [c]
: p["#"] ? p["#"].push(c)
: p["#"] = [c];
return p;
},{}),
result = Object.keys(table).reduce(function(p,k){
return p.concat({letter: k, isLetter: true},table[k]);
},[]);
console.log(result);
至少有两个原因导致您的代码没有给出预期的结果:
您使用的索引指向原始数组中的索引。由于您的新数组将包含更多元素,因此将该索引用于新数组上的
splice
是没有意义的。它最终会指向错误的地方;你只压入
prev
元素,所以最后一个元素永远不会被压入结果数组
我建议使用 reduce
和一个累加值(回调的第一个参数)来构建最终数组。为了记住介绍的最后一个字母对象,我将把这个累积值与那个字母配对。所以我将使用包含两个元素的数组:
- 正在累积的最终数组
- 最近添加的字母对象的字母
那么最终结果将从该数组的第一个元素中获取,忽略第二个值。
我建议不要使用字符代码,而只使用字符。它使您免于将代码转换回字符。
代码如下:
var list = [
{name: '4 Arn', isLetter: false},
{name: 'Abax', isLetter: false},
{name: 'Aramex', isLetter: false},
{name: 'Booking', isLetter: false},
{name: 'Dangerous', isLetter: false},
{name: 'Manali', isLetter: false}
];
var newArr = list.reduce(function(collect, cur, index, originalArrray) {
var currentChar = cur.name.toUpperCase().substr(0,1);
if (currentChar < 'A') currentChar = '#';
if (collect[1] != currentChar) {
collect[0].push({isLetter: true, letter: currentChar});
collect[1] = currentChar;
}
collect[0].push(cur);
return collect;
}, [[], null])[0];
// output
console.log(newArr);