【问题标题】:Vue: sort array based on object orderVue:根据对象顺序对数组进行排序
【发布时间】:2019-03-28 13:04:18
【问题描述】:

给定一个这样的数组:

var endArray = [34, 35, 32]

还有一个像这样的对象:

var order = [{"id":35},{"id":34},{"id":32},{"id":30},{"id":28},{"id":24},{"id":17},{"id":15},{"id":3}]

order 更改时,如何重新排序endArray?我在 Vue 工作,所以我可以像这样写一个观察者:

watch: {
  order: function (newObject) {
    // resort endArray here somehow
  }
}

但我不确定如何将订单映射到排序endArray

更新

预期结果是:

endArray = [35, 34, 32]

匹配order中设置的id键的顺序。

【问题讨论】:

  • 你想根据order数组的顺序对endArray进行排序吗?
  • 请添加输入和想要的结果。
  • 我已经更新了问题。
  • 为什么不从给定的对象创建数组?
  • 除了我如何简化 SO 问题之外,还有其他因素在起作用,即数组控制所选的 ID,对象控制顺序。

标签: javascript vue.js ecmascript-6 vuejs2


【解决方案1】:

您可以对数组进行切片以获取前三个对象并映射id

watch: {
    order: function (newObject) {
        endArray = newObject.slice(0, 3).map(({ id }) => id);
    }
}

另一种解决方案是对数组进行排序。

watch: {
    order: function (newObject) {
        const getIndex = id => newObject.findIndex(o => o.id === id);
        endArray.sort((a, b) => getIndex(a) - getIndex(b));
    }
}

【讨论】:

  • 既然我们有一个原语数组,我认为最好使用indexOf方法。
  • @MihaiAlexandru-Ionut,order 数组包含对象,正如我所见...
  • 不得不选择这个,因为它非常简洁并且是第一个有效的。 谢谢。
  • 你甚至可以创建一个计算属性:endArray() { return newObject.slice(0, 3).map(({ id }) => id); }
【解决方案2】:

创建一个数组以查找 id 并按给定数组的长度拆分它/或直接提供长度(如果在此处知道)3

var endArray = [34, 35, 32];
var order = [{"id":35},{"id":34},{"id":32},{"id":30},{"id":28},{"id":24},{"id":17},{"id":15},{"id":3}];
var orderIds = order.map(function(e){return e.id});
console.log(orderIds.splice(0,endArray.length));

【讨论】:

    【解决方案3】:

    解决这个问题的方法是将问题分步:

    由于要对数组进行排序,所以要调用endArray.sort((a, b) => {})

    你想对什么进行排序?可以找到id的索引:

    endArray.sort((a, b) => {
        let indexA;
        for(indexA = 0; indexA < this.order.length; indexA++) {
            if (this.order[indexA].id === a) break;
        }
        let indexB;
        for(indexB = 0; indexB < this.order.length; indexB++) {
            if (this.order[indexB].id === b) break;
        }
        // ...
    })
    

    我们要如何排序?升序:

    endArray.sort((a, b) => {
        let indexA;
        for(indexA = 0; indexA < this.order.length; indexA++) {
            if (this.order[indexA].id === a) break;
        }
        let indexB;
        for(indexB = 0; indexB < this.order.length; indexB++) {
            if (this.order[indexB].id === b) break;
        }
        if (indexA > indexB) return 1;
        if (indexB > indexA) return -1;
        return 0;
    })
    

    我们什么时候要对它进行排序?当ordernewArray 发生变化时:

    new Vue({
        el: '#app',
        data: {
            orderString: '[{"id":35},{"id":34},{"id":32},{"id":30},{"id":28},{"id":24},{"id":17},{"id":15},{"id":3}]',
            newArrayString: '[34, 35, 32]',
        },
        computed: {
            order() {
                return JSON.parse(this.orderString);
            },
            newArray() {
                return JSON.parse(this.newArrayString);
            },
            result() {
                //  Make a copy to prevent editing the original data
                return [...this.newArray].sort((a, b) => {
            let indexA;
            for(indexA = 0; indexA < this.order.length; indexA++) {
                if (this.order[indexA].id === a) break;
            }
            let indexB;
            for(indexB = 0; indexB < this.order.length; indexB++) {
                if (this.order[indexB].id === b) break;
            }
            if (indexA > indexB) return 1;
            if (indexB > indexA) return -1;
            return 0;
        })
            }
        },
    })
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    
    <div id="app">
        <p>
            Order:
            <textarea v-model="orderString"></textarea>
        </p>
        <p>
            NewArray:
            <textarea v-model="newArrayString"></textarea>
        </p>
        <p>
            Result:
            {{ result }}
        </p>
    </div>

    【讨论】:

      【解决方案4】:

      只需通过传递callback 提供的函数来使用sort 方法。我使用indexOf 函数来找到指定elementindex

      var endArray = [34, 35, 32]
      var order = [{"id":35},{"id":34},{"id":32},{"id":30},{"id":28},{"id":24},{"id":17},{"id":15},{"id":3}]
      
      var orderIds = order.map(({id}) => id);
      endArray.sort((a,b) => orderIds.indexOf(a) - orderIds.indexOf(b));
      console.log(endArray);

      【讨论】:

        【解决方案5】:
        function compare(a,b) {
          if (order.indexOf(a.id) > order.indexOf(b.id))
            return -1;
        
          if (order.indexOf(a.id) < order.indexOf(b.id))
            return 1;
        
          return 0;
        }
        
        endArray.sort(compare);
        

        看起来您正在寻找数组上的排序函数。基本上,您创建一个比较器并将该函数传递给排序函数。

        在您的情况下,您将在比较器中包含用于检查/比较订单数组值的逻辑。

        更多信息: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

        【讨论】:

        • 您答案中的last_nom 变量来自哪里?它不在问题之内。
        • 我的错,使用了我在编辑器中提供的示例。
        • 在您的新示例中,您似乎混淆了newArrayorder 的内容,newArray 是数字列表,order 是包含键的对象列表-值对:id: number
        猜你喜欢
        • 2013-11-25
        • 1970-01-01
        • 2012-04-03
        • 2022-01-28
        • 2020-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多