【问题标题】:js: loop through object and count occurrences strings and create a ranking from the occurrencesjs:遍历对象并计算出现的字符串并根据出现的次数创建排名
【发布时间】:2021-06-22 18:12:30
【问题描述】:

我有一个带有对象的对象,我想显示出现次数最多的名称排名。

喜欢

  1. 约翰
  2. 玛丽亚
  3. 乔什

这是我的对象:

let data = {
    "1111": {
      firstName: "john",
      lastName: "doe",
    },
    "1112": {
      firstName: "john",
      lastName: "doe",
    },
    "1113": {
      firstName: "maria",
      lastName: "dee",
    },
    "1114": {
      firstName: "john",
      lastName: "doe",
    },
    "1115": {
      firstName: "maria",
      lastName: "dee",
    },
    "1116": {
      firstName: "josh",
      lastName: "kek",
    },
    "1117": {
      firstName: "maria",
      lastName: "dee",
    },
    "1118": {
      firstName: "nick",
      lastName: "smith"
    }

  }

我用 for in 循环尝试了一些事情,但我没有做对...

for (let key in data) {
    let firstFind = data[key]["firstName"]
    let firstCounter = 0

    if(data[key]["firstName"] = firstFind) {
        firstCounter++
    } else {
        let secondFind = data[key]["firstname"]
        let secondCounter = 0
        
        if(data[key]["firstName"] = secondFind) {
            secondCounter++
        }

        //...reproduce until there is no new name
        //this is where my limit is
            
    }
    


  }

代码应该循环遍历所有对象,计算名称,并创建出现次数最多的名称的排名。见上例

【问题讨论】:

  • 请添加你的代码,你试过了。两个或多个相同的计数会发生什么?
  • Object.values() + "javascript group array of objects" 答案之一 + .sort()
  • 谢谢,我试试!

标签: javascript string loops object count


【解决方案1】:

您基本上可以使用Object.entries() 来获取key value 对的可迭代数组,然后执行类似的操作

const data = {} // insert your object here
const dupes = [];
for (const [key, value] of Object.entries(data)) {
    const elem = dupes.find(x => x.firstName === value.firstName); // if there is an element in the array
    if (elem) elem.count = elem.count + 1; // increase count by 1
    else { 
    const dat = { firstName: value.firstName, lastName: value.lastName, count: 1 };
    dupes.push(dat); // initiating a new element with count 1
    }
}
const sortArr = dupes.sort((a, b) => b.count - a.count);
console.log(sortArr[0]) // returns the element with highest count.
// in your case this would be the output
// {firstName: 'john', lastName: 'doe', count: 3}

// update to get the list in order
const lbArr = [];
sortArr.forEach(x => lbArr.push(`${x.firstName} ${x.lastName} ${x.count}`))
console.log(lbArr.join('\n'))

P.S 你也可以使用Object.values(),我使用Object.entries() 以防你想将密钥分配给 dupes 数组。

【讨论】:

  • 非常感谢!!有什么办法可以修改它以获得第二和第三高的计数?
  • @TimSchneider sortedArr 是一个数组,您可以将 sortedArr[1] 记录为第二个值等
  • @TimSchneider 实际上等不及为此编写代码
  • @TimSchneider 如果可行,请考虑将其标记为正确答案:D
  • 这个答案不正确。有 2 个名称具有相同的最高计数,但这仅返回其中一个。这不考虑关系。
【解决方案2】:

这是另一种方法,它产生一个考虑关系的可读对象。我将注释代码以使其可读。这是您的数据的输出:

{ "first": [
    {"name": "john doe", "count": 3},
    {"name": "maria dee", "count": 3}
  ],
  "second": [
    {"name": "josh kek", "count": 1},
    { "name": "nick smith", "count": 1}
  ],
  "third": []
}

let data = {
    "1111": { firstName: "john",lastName: "doe" },
    "1112": { firstName: "john",lastName: "doe" },
    "1113": { firstName: "maria",lastName: "dee" },
    "1114": { firstName: "john",lastName: "doe" },
    "1115": { firstName: "maria",lastName: "dee" },
    "1116": { firstName: "josh",lastName: "kek" },
    "1117": { firstName: "maria",lastName: "dee" },
    "1118": { firstName: "nick",lastName: "smith" }
  }

let ranking =
  // we want to iterate through the {firstName:...} in each object so we use Object.values()
  // but we can't iterate objects like this so we wrap it in Object.entries, which turns it into an array
  Object.entries(Object.values(data)
  // this first reduce function does the counting and sets up an object of {name: count}
  .reduce((b, {firstName,lastName}) => {
    let n = firstName + ' ' + lastName;
    // setting up a counter and using the whole name as a key (there may be more than one JOhn)
    b[n] = b.hasOwnProperty(n) ? b[n] + 1 : 1;
    return b
  }, {}))
  // wrapped in Objct.entries, this is an array which we can sort
  .sort(([, a], [, b]) => b - a)
  // the last reduce transfers the sorted {name: count} object into first second and third arrays
  .reduce((b, a) => {
      let v = { name: a[0], count: a[1]},
        placed = false;
      // we iterate through first, second and third and fill them in
      ['first', 'second', 'third'].forEach(p => {
        if (!placed && ((b[p].length > 0 && b[p][0].count === a[1]) || b[p].length === 0)) {
          b[p].push(v);
          placed = true;
        }
      });
       return b
      }, {first: [], second: [], third: [] });

console.log(ranking)


// all that can be optimized to this:
Object.entries(Object.values(data).reduce((b, {firstName,lastName}) => {
    let n = firstName + ' ' + lastName;  b[n] = b.hasOwnProperty(n) ? b[n] + 1 : 1; return b;
  }, {})).sort(([, a], [, b]) => b - a).reduce((b, a) => {
      let v = { name: a[0], count: a[1]}, placed = false;
      ['first', 'second', 'third'].forEach(p => {
        if (!placed && ((b[p].length > 0 && b[p][0].count === a[1]) || b[p].length === 0)) {
          b[p].push(v); placed = true;
        }}); return b;
      }, {first: [], second: [], third: [] });
      

【讨论】:

    【解决方案3】:

    一种相当简单的方法是使用reduce 将计数收集到一个对象中,获取该对象的条目,然后按计数对它们进行排序:

    const namesByCount = (xs) =>
      Object.entries (Object .values (xs) .reduce (
        (a, {firstName}) => ((a [firstName] = (a [firstName] || 0) + 1), a), 
        {}
      )) .sort (([, a], [, b]) => b - a) //.map (([a]) => a)
    
    let data = {1111: {firstName: "john", lastName: "doe"}, 1112: {firstName: "john", lastName: "doe"}, 1113: {firstName: "maria", lastName: "dee"}, 1114: {firstName: "john", lastName: "doe"}, 1115: {firstName: "maria", lastName: "dee"}, 1116: {firstName: "josh", lastName: "kek"}, 1117: {firstName: "maria", lastName: "dee"}, 1118: {firstName: "nick", lastName: "smith"}}
    
    console .log (namesByCount (data))
    .as-console-wrapper {max-height: 100% !important; top: 0}

    如果您只想要名称,可以取消注释 .map 调用。

    逗号操作符的使用有点棘手。我更喜欢使用表达式而不是语句。但如果它困扰你,你可以这样做:

    const namesByCount = (xs) =>
      Object.entries (Object .values (xs) .reduce (
        (a, {firstName}) => {
          a [firstName] = a [firstName] || 0
          a [firstName] += 1
          return a
        },
        {}
      )) .sort (([, a], [, b]) => b - a) //.map (([a]) => a)
    

    【讨论】:

      猜你喜欢
      • 2021-08-11
      • 1970-01-01
      • 1970-01-01
      • 2021-10-17
      • 2019-08-23
      • 2012-12-03
      • 2012-06-24
      • 2023-01-28
      • 1970-01-01
      相关资源
      最近更新 更多