Vue/Javascript—根据对象在另一个数组中的存在情况对其进行排序

Vue/Javascript—根据对象在另一个数组中的存在情况对其进行排序,javascript,arrays,sorting,object,vuejs2,Javascript,Arrays,Sorting,Object,Vuejs2,我有两个数组,array1包含所有对象,array2基于搜索字符串过滤对象 目前,我正在向用户呈现array2(搜索字符串为空时,它将包含array1中的所有对象,但如果搜索字符串不为空,则仅返回过滤对象),但我希望显示所有对象并设置过滤对象(与搜索匹配的对象)的样式以不同的方式,将匹配搜索查询的对象保留在数组/列表的顶部,如果我还可以按字母顺序对匹配的对象进行排序,我很乐意这样做 以下是我如何根据搜索查询进行筛选: export default { name: "Region

我有两个数组,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;
      },
    },
};
导出默认值{
名称:“地区选民”,
数据:()=>({
searchRegionTextValue:“”,
区域:[
{
国家:“美国”,
国旗:“美国国旗”,
名称:“美国”,
语言:“英语”,
},
{
国家:“英国”,
国旗:“国旗en gb”,
名称:“联合王国”,
语言:“英语”,
},
{
国家:“德”,
旗帜:“德旗”,
名称:“德国”,
语言:“德语”,
},
],
}),
方法:{
//在模板中的“我的v-for”中使用,以对不匹配的结果进行不同的样式设置
检查区域(区域){
伊西纳雷变种=
this.filteredRegions.find(函数(el){
返回el==区域;
})!==未定义;
返回isInArray;
},
计算:{
过滤区域(){
功能比较(a、b){
如果(a.nameb.name)返回1;
返回0;
}
让regions=this.regions.filter((region)=>{
返回(
region.name
.toLowerCase()
.indexOf(this.searchRegionTextValue.toLowerCase())!=-1||
地区语言
.toLowerCase()
.indexOf(this.searchRegionTextValue.toLowerCase())!=-1
);
});
区域。排序(比较);
返回区;
},
},
};
在我的模板中,我以这种方式渲染它们(以显示所有对象,但样式不同):


{{region.name}

如何实现上述排序?

您可以引入第二个
计算的
方法,该方法包含未匹配的对象,并对该数组执行另一个
for loop

“可能”更有效,引入另一个属性将对象标记为匹配对象,并将该属性用于排序逻辑

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;
  },
},
计算:{
新区域(){
功能比较(a、b){
如果(a.matched&&!b.matched)返回-1;
如果(!a.matched&&b.matched)返回1;
如果(a.匹配和b.匹配){
如果(a.nameb.name)返回1;
}
返回0;
}
让regions=this.regions.map((region)=>({
区域
匹配:region.name
.toLowerCase()
.indexOf(this.searchRegionTextValue.toLowerCase())!=-1||
地区语言
.toLowerCase()
.indexOf(this.searchRegionTextValue.toLowerCase())!=-1
}));
区域。排序(比较);
返回区;
},
},
然后在你的模板上

<div v-for="region in newregions">
    <span
    :class="region.matched ? 'matched-query' : 'unmatched-query'">
        {{region.name}}
    </span>
</div>

{{region.name}

您可以引入第二个
计算的
方法,该方法包含未匹配的对象,并对该数组执行另一个
for loop

“可能”更有效,引入另一个属性将对象标记为匹配对象,并将该属性用于排序逻辑

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;
  },
},
计算:{
新区域(){
功能比较(a、b){
如果(a.matched&&!b.matched)返回-1;
如果(!a.matched&&b.matched)返回1;
如果(a.匹配和b.匹配){
如果(a.nameb.name)返回1;
}
返回0;
}
让regions=this.regions.map((region)=>({
区域
匹配:region.name
.toLowerCase()
.indexOf(this.searchRegionTextValue.toLowerCase())!=-1||
地区语言
.toLowerCase()
.indexOf(this.searchRegionTextValue.toLowerCase())!=-1
}));
区域。排序(比较);
返回区;
},
},
然后在你的模板上

<div v-for="region in newregions">
    <span
    :class="region.matched ? 'matched-query' : 'unmatched-query'">
        {{region.name}}
    </span>
</div>

{{region.name}

使用spread操作符将原始数组附加到过滤数组的结果中,如下所示

[…过滤器区域(),…区域]
这会将匹配项添加到数组的开头,接下来我们将从数组中删除重复项,只需将
new Set()
包装在数组周围即可,如下所示

const newRegions=新集合([…filteredRegions(),…regions])
您可以像这样将其转换为普通数组

const newRegions=[…新集合([…filteredRegions(),…regions])]
参见下面的示例代码:

const regions=[
{
国家:“美国”,
国旗:“美国国旗”,
名称:“美国”,
语言:“英语”,
},
{
国家:“英国”,
国旗:“国旗en gb”,
名称:“联合王国”,
语言:“英语”,
},
{
国家:“德”,
旗帜:“德旗”,
名称:“德国”,
语言:“德语”,
},
{
国家:“NG”,
国旗:“ng旗”,
名称:“尼日利亚”,
语言:“英语”,
},
]
功能比较(a、b){
如果(a.nameb.name)返回1;
返回0;
}
函数filteredRegions(查询='Nigeria'){
让区域=区域。过滤器((区域)=>{
返回(
region.name
.toLowerCase()
.indexOf(query.toLowerCase())!=-1 | | region.language
.toLowerCase()
.indexOf(query.toLowerCase())!=-1
);