2016-08-03 45 views
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; 
}); 
+1

我可以问你为什么想去该结构?这真的不是那么好的设计。更好的做法是将具有相同起始字母的节点放置为字母节点的子节点,以便在顶层只有字母节点,并且仅在第二层有原始节点。 – trincot

+0

其用于离子列表视图。 –

回答

3

至少有两方面的原因,为什么你的代码不会产生预期的结果:

  • 你一起工作的指标,指向原始数组中的索引。由于新阵列将具有更多元素,因此在新阵列上使用该索引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);

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

+0

我想每个新的第一个字母只插入一次新的对象,而不是每次。 –

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

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

相关问题