【问题标题】:Creating alphabetic grouped list from contacts从联系人创建字母分组列表
【发布时间】:2017-07-31 10:26:02
【问题描述】:

我有一个需要两个数组的函数。第一个数组称为字母,包括联系人数组中的所有(唯一)起始字母。第二个参数采用上述联系人数组。

该函数应该根据他们的起始字母对所有联系人进行分组,并为每个字母和包括联系人创建一个新数组和对象。该对象应如下所示:

{
"letter": "S", 
"names": [Sample1, Sample2, Sample3] 
}

该功能已经工作,但有一个问题。如果有多个联系人具有相同的起始字母,则数组将被最后一个联系人覆盖,因此名称的最大值始终为 1。这是我创建包含所有对象的数组的函数:

function groupContacts(letters, contacts) {
  var groupedContacts = [];
  for (var i = 0; i < contacts.length; i++) {
    for (var j = 0; j < letters.length; j++) {
      if (
        letters[j].toLowerCase() === contacts[i].toLowerCase().substring(0, 1)
      ) {
        let names = []
        names.push(contacts[i])
        groupedContacts[j] = {
          letter: letters[j],
          name: names
        };
      }
    }
  }
  console.log(groupedContacts, "grouped Contacts");
}

感谢您的帮助!

PS:这里是 jsfiddle https://jsfiddle.net/bn7f8tsx

【问题讨论】:

  • 请提供数据。
  • jsfiddle.net/bn7f8tsx 这里是一个样本数据。谢谢
  • @zbkrt 当有人要求提供更多信息时,请在您的问题中更新,不要作为评论发布

标签: javascript arrays


【解决方案1】:

您可以尝试创建letters: names 的映射,然后遍历该映射的键并创建您的结构。

let contacts = ["Simon", "Mike", "Jake", "Lara", "Susi", "Blake", "James"];

var map = contacts.reduce((p, c) => {
  let char = c.charAt(0).toUpperCase();
  p[char] = [].concat((p[char] || []), c)
  return p;
}, {});

var result = Object.keys(map).map(k => ({
  letter: k,
  names: map[k]
}));

console.log(result);

【讨论】:

  • 很好的解决方案,我也准备了 reduce,但这更有效
  • @Jonasw 首先,它不会是 O(n^2),因为您只有 26 个字符,如果我们的名称包含所有字符,则需要多 26 次迭代。其次,if 条件也需要很长时间。第三,即使您的解决方案也有 2 个循环,最终我猜我们都会有相似的迭代次数
  • @rajesh 是的,最坏的情况是 26 个名字的开头字母不同... ;) (我的错误是 O(2n)),我的第一个解决方案在 O(n) 中运行。但是,这仍然是一个很好的解决方案...
【解决方案2】:

我使用了reduce 模式,因为它是为解决这类问题而设计的。

  1. 使用Array.reduce 创建了一个分组列表
  2. Array.sort排序

Fiddle

let contacts = [
    "Simon",
    "Mike",
    "Jake",
    "Lara",
    "Susi",
    "Blake",
    "James"
];

var contactsGrouped = contacts.reduce(function(contactList, name) {
        var contactLetterGroup = contactList.filter(function(list) {
            return list.letter == name[0].toUpperCase();
        });
        if (contactLetterGroup.length > 0) {
            contactLetterGroup[0].name.push(name);
        } else {
            contactList.push({
                letter: name[0].toUpperCase(),
                name: [name]
            });
        }
        return contactList;
    }, [])
    .sort(function(a, b) {
        return b.letter - a.letter;
    })

console.log(contactsGrouped);

【讨论】:

    【解决方案3】:

    你可以使用哈希表(所以你不需要每次都搜索字母),这也不需要字母数组:

    function groupContacts(contacts) {
      var groupedContacts = [],hash={};
      contacts.forEach(function(contact){    
        var letter = contact.toLowerCase().substring(0, 1)
        if(hash[letter]){
         hash[letter].names.push(contact);
        }else{       
         groupedContacts.push(hash[letter]= {
          letter,
          names: [contact]
        });
       }
    });
    console.log(groupedContacts, "grouped Contacts");
    return groupedContacts;
    }
    

    Try it

    或者你使用你的旧版本并改进逻辑(有点慢),你也不需要这里的字母:

    function groupContacts(contacts) {
     var groupedContacts = [];
     contLoop:for (var i = 0; i < contacts.length; i++) {
       for (var j = 0; j < groupedContacts.length; j++) {
        if (
        groupedContacts[j].letter.toLowerCase() === 
        contacts[i].toLowerCase().substring(0, 1)
        ) {
         groupedContacts[i].names.push(contacts[i]);
         continue contLoop;//exit is important
       }
      }
      //no letter found, create new
        groupedContacts[j] = {
          letter: contacts[i].toLowerCase().substring(0, 1),
          names:[contacts[i]]
        };
    }
      console.log(groupedContacts, "grouped Contacts");
      return groupedContacts;
    }
    

    Try it

    【讨论】:

    • 可以试试.substring(0, 1),而不是charAt(0)
    • @rajesh 是的,好点,但我认为这不是关于性能的大问题。
    【解决方案4】:

    您可以使用哈希表并收集字母的数组。

    function groupNames(array) {
        var hash = Object.create(null),
            result = [];
            
        array.forEach(function (a) {
            var k = a[0].toUpperCase();
            if (!hash[k]) {
                hash[k] = [];
                result.push({ letter: k, names: hash[k] });
            }
            hash[k].push(a);
        });
        return result;
    }
    
    console.log(groupNames(['Anne', 'Bert', 'Claudine', 'Dirk', 'Anton', 'Babette', 'Eugen', 'Felicitas']));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

      【解决方案5】:

      您只需将let names = [] 字符串放在循环之外;

      function groupContacts(letters, contacts) {
        var groupedContacts = [];
        let names = []
        for (var i = 0; i < contacts.length; i++) {
          for (var j = 0; j < letters.length; j++) {
            if (
              letters[j].toLowerCase() === contacts[i].toLowerCase().substring(0, 1)
            ) {
              
              names.push(contacts[i])
              groupedContacts[j] = {
                letter: letters[j],
                name: names
              };
            }
          }
        }
        console.log(groupedContacts, "grouped Contacts");
      }
      
      groupContacts('S',['Sarah', 'John','Silvester', 'Tracy','Sean'])

      【讨论】:

      • 传入字母数组时对我不起作用
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-21
      • 1970-01-01
      • 2013-01-11
      • 2012-04-22
      • 1970-01-01
      相关资源
      最近更新 更多