0

我有以下 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;
});
4

4 回答 4

4

您的代码没有给出预期结果的原因至少有两个:

  • 您使用的索引指向原始数组中的索引。由于您的新数组将包含更多元素,因此将该索引用于splice新数组上的 a 是没有意义的。它最终会指向错误的地方;

  • 你只推送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);

于 2016-08-03T12:41:34.117 回答
1

我想你也可以用这样的功能方式来做;

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" 返回 NaN 但 +"4" 返回 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);

于 2016-08-03T12:35:53.817 回答
1

也许通过这种方法,您可以解决问题

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));

于 2016-08-03T12:25:11.027 回答
1

检查此解决方案。迭代数组并将其附加到新数组。

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);

于 2016-08-03T12:05:14.063 回答