【问题标题】:Iterate an object with reverse sorted keys使用反向排序的键迭代对象
【发布时间】:2018-07-10 11:01:49
【问题描述】:

我知道我的问题标题可能会令人困惑(我知道对象属性没有顺序),因为我已经提出了解决方案,所以为了避免创建 XY problem,让我先解释一下我的目标:

我需要呈现 N 个按字长分组的单词表,并且(这是棘手的事情)按长度降序排列。比如:

Words with length 4
===================
abcd | other fields
abce | other fields 
abcf | other fields

Words with length 3
===================
abc  | other fields
abd  | other fields
abe  | other fields

Words with length 2
===================
...

我从一个没有任何分组的 API 获取我的单词列表,所以我现在正在做的是:

let grouped = {};
// Assume words is an Array of words of multiple lengths
words.forEach(w => {
    if (typeof grouped[w.length] === 'undefined')
        grouped[w.length] = [];
    grouped[w.length].push({'word': w}); 
    // Pushing an object cause of other calculated and not rellevant fields
});

当然,当我渲染这个 grouped 单词时(我使用的是 Vue.js)...

<WordsTable 
    v-for="(group, length) in grouped"
    :words="group"
    :word-length="length"
/>

我使用 word-length 属性来渲染表格的标题长度为 N 的单词。

一切正常,但我按升序顺序获得表格(而且,我再次意识到这可能是巧合,因为对象中没有顺序)。所以真正的问题是,谁能想出办法让 Vue 用降序键迭代我的 grouped 对象?

注意:可能没有特定长度的单词,所以Object.keys(grouped) 可能是[3,4,7,9,10]

更新:

评论者建议对grouped 使用数组而不是对象。我已经尝试过了,确实可能会稍微好一点,但并不能完全解决问题。

如果grouped是一个数组,我可以反转它:

<WordsTable 
    v-for="(group, length) in grouped.reverse()"
    ...
/>

但在这种情况下,索引会丢失,不能再用于呈现表格的标题。

【问题讨论】:

  • 您可以将单词存储在数组而不是对象中。将let grouped = {} 替换为let grouped = []
  • 我试过了。也不行。让我用更多信息更新我的问题。

标签: javascript vue.js vuejs2 javascript-objects


【解决方案1】:

您可以创建一个计算属性,按降序对对象键进行排序:

sortedGroupKeys() { 
    return Object.keys( group ).sort( ( a , b ) => b - a); 
}

然后你可以循环它。

<WordsTable 
    v-for="(key in sortedGroupKeys)"
    :words="group[ key ]"
    :word-length="key"
/>

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    这应该可行。遍历键的排序列表。

    console.clear()
    
    Vue.component("WordsTable",{
      props: ["words", "length"],
      template: `
        <table>
          <caption>Words of length {{length}}</caption>
          <tbody>
            <tr v-for="word in words"><td>{{word}}</td></tr>
          </tbody>
        </table>  
      `
    })
    new Vue({
      el: "#app",
      data:{
        words: [
          "hello", "apple", "mister", "wut", "phenomenal", "and", "vue", "four", "word"
        ]
      },
      computed:{
        grouped() {
          return this.words.reduce((groups, word) => {
            (groups[word.length] = groups[word.length] || []).push(word)
            return groups
          }, {})
        },
        sortedDesc(){
          return Object.keys(this.grouped).sort((a,b) => b - a)
        }
      }
    })
    caption {
     text-align: left;
     border-bottom: 1px solid black;
    }
    
    table {
      width: 10em;
      margin-bottom: 1em;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
    <div id="app">
      <words-table v-for="length in sortedDesc" :key="length" :words="grouped[length]" :length="length"></words-table>
    </div>

    【讨论】:

    • 非常感谢,伯特。您的解决方案完美运行,但我将选择 Tarik 的,因为它不需要另一个级别的迭代(哦,现在我看到您编辑删除了这个额外的 v-for)。无论如何,我正在选择您的基于reduce() 的分组!感谢您的时间/帮助!
    • @JordiNebot 他的回答完全一样。
    • 是的,它使用完全相同的想法,但恕我直言,他首先将它更好地应用于我当前的组件。您稍后进行了编辑以删除额外的v-for。我的意思是,这不是一场比赛,我很感谢你们俩,但在我接受答案时,他更适合我的代码。
    • @JordiNebot 有两个循环(组件必须遍历单词)。无论如何,祝你好运。
    猜你喜欢
    • 2016-06-10
    • 2021-04-08
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2020-06-02
    • 1970-01-01
    • 2017-05-14
    • 2023-03-08
    相关资源
    最近更新 更多