[英]Vue/Javascript - Sort array of objects based on its existence in another array
我有两个 arrays,array1 包含所有对象,array2 包含基于搜索字符串的过滤对象。
目前我正在向用户渲染array2(当搜索字符串为空时,它将包含来自array1的所有对象,但如果搜索字符串不为空,则仅返回过滤的对象)但我想显示所有对象并设置过滤后的对象(那些与搜索匹配的)以不同的方式保留那些匹配搜索查询的数组/列表的顶部,如果我什至除此之外还可以按字母顺序对那些匹配的对象进行排序,我会喜欢。
这是我根据搜索查询进行过滤的方式:
export default {
name: "RegionSelector",
data: () => ({
searchRegionTextValue: "",
regions: [
{
country: "USA",
flag: "flag-en-us",
name: "United States",
language: "English",
},
{
country: "UK",
flag: "flag-en-gb",
name: "United Kingdom",
language: "English",
},
{
country: "DE",
flag: "flag-de",
name: "Germany",
language: " German",
},
],
}),
methods: {
// Used in my v-for in the template to style non-matched results differently
checkRegion(region) {
var isInArray =
this.filteredRegions.find(function(el) {
return el === region;
}) !== undefined;
return isInArray;
},
computed: {
filteredRegions() {
function compare(a, b) {
if (a.name < b.name) return -1;
if (a.name > b.name) return 1;
return 0;
}
let regions = this.regions.filter((region) => {
return (
region.name
.toLowerCase()
.indexOf(this.searchRegionTextValue.toLowerCase()) != -1 ||
region.language
.toLowerCase()
.indexOf(this.searchRegionTextValue.toLowerCase()) != -1
);
});
regions.sort(compare);
return regions;
},
},
};
在我的模板中,我以这种方式渲染它们(显示所有对象,但样式不同):
<div v-for="region in regions">
<span
:class="checkRegion(region) ? 'matched-query' : 'unmatched-query'">
{{region.name}}
</span>
</div>
如何实现上述排序?
使用扩展运算符将 append 原始数组转换为过滤数组的结果,如下所示
[...filteredRegions(), ...regions]
这会将匹配项添加到数组的开头,接下来我们从数组中删除重复项,我们可以通过将new Set()
包裹在它周围来做到这一点,就像这样
const newRegions = new Set([...filteredRegions(), ...regions])
您可以像这样将其转换为普通数组。
const newRegions = [...new Set([...filteredRegions(), ...regions])]
请参阅下面的示例代码:
const regions = [
{
country: "USA",
flag: "flag-en-us",
name: "United States",
language: "English",
},
{
country: "UK",
flag: "flag-en-gb",
name: "United Kingdom",
language: "English",
},
{
country: "DE",
flag: "flag-de",
name: "Germany",
language: " German",
},
{
country: "NG",
flag: "flag-ng",
name: "Nigeria",
language: "English",
},
]
function compare(a, b) {
if (a.name < b.name) return -1;
if (a.name > b.name) return 1;
return 0;
}
function filteredRegions(query = 'Nigeria') {
let regions = regions.filter((region) => {
return (
region.name
.toLowerCase()
.indexOf(query.toLowerCase()) != -1 || region.language
.toLowerCase()
.indexOf(query.toLowerCase()) != -1
);
});
regions.sort(compare);
return regions;
}
let result = [...new Set([...filteredRegions(), ...regions])]
您可以引入第二个包含不匹配对象的computed
方法,并为该数组执行另一个for loop
或者
“可能”更有效,引入另一个属性将 object 标记为匹配的 object,并将该属性用于排序逻辑
computed: {
newregions() {
function compare(a, b) {
if (a.matched && !b.matched) return -1;
if (!a.matched && b.matched) return 1;
if (a.matched && b.matched) {
if (a.name < b.name) return -1;
if (a.name > b.name) return 1;
}
return 0;
}
let regions = this.regions.map((region) => ({
...region,
matched: region.name
.toLowerCase()
.indexOf(this.searchRegionTextValue.toLowerCase()) != -1 ||
region.language
.toLowerCase()
.indexOf(this.searchRegionTextValue.toLowerCase()) != -1
}));
regions.sort(compare);
return regions;
},
},
然后在你的模板上
<div v-for="region in newregions">
<span
:class="region.matched ? 'matched-query' : 'unmatched-query'">
{{region.name}}
</span>
</div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.