2016-08-03 86 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);

相關問題