繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM