最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Vue: sort array based on object order - Stack Overflow

programmeradmin4浏览0评论

Given an array like this:

var endArray = [34, 35, 32]

And an object like this:

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

How can I re-sort endArray when order is changed? I'm working in Vue so I can write a watcher like so:

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

But I'm not sure how to map the order to sort endArray.

Update

Expected result is:

endArray = [35, 34, 32]

To match the order of id keys set in order.

Given an array like this:

var endArray = [34, 35, 32]

And an object like this:

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

How can I re-sort endArray when order is changed? I'm working in Vue so I can write a watcher like so:

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

But I'm not sure how to map the order to sort endArray.

Update

Expected result is:

endArray = [35, 34, 32]

To match the order of id keys set in order.

Share Improve this question edited Oct 24, 2018 at 7:59 t56k asked Oct 24, 2018 at 7:47 t56kt56k 7,03110 gold badges58 silver badges121 bronze badges 5
  • 1 Do you want to sort endArray based on order of order array ? – Mihai Alexandru-Ionut Commented Oct 24, 2018 at 7:49
  • 1 please add input and the wanted result. – Nina Scholz Commented Oct 24, 2018 at 7:50
  • I've updated the question. – t56k Commented Oct 24, 2018 at 7:54
  • why not you create array from object given ? – Niklesh Raut Commented Oct 24, 2018 at 7:56
  • There are other factors at play beyond how I've simplified the problem for SO, i..e, the array controls the IDs selected, the object controls the order. – t56k Commented Oct 24, 2018 at 7:58
Add a ment  | 

5 Answers 5

Reset to default 3

You could slice the array for getting the first three objects and map id.

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

A different solution could be to sort the array.

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

Make an array to find ids and split it by length of given array/OR direct provide length if known here 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));

The way to solve this problem is to divide the problem in steps:

Since you want to sort the array, you want to call endArray.sort((a, b) => {})

On what do you want to sort? The index where the idcould be found:

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;
    }
    // ...
})

How do we want to sort it? ascending:

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;
})

When do we want to sort it? When order or newArray changes:

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]',
    },
    puted: {
        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/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>

Just use sort method by passing a callback provided function. I used indexOf function in order to find the index of a specified element.

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);

function pare(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(pare);

Looks like you're looking for the sort function on an array. Basically, you create a parer and pass the function to the sort function.

In your situation, you would include logic to check/pare the values against the order array, in the parer.

More info: https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

发布评论

评论列表(0)

  1. 暂无评论