【问题标题】:Sorting array based on matched and unmatched values using es6使用 es6 根据匹配和不匹配的值对数组进行排序
【发布时间】:2020-04-09 00:21:47
【问题描述】:

这可能是一个简单的问题,但我已经坚持了一段时间以使其变得简单。

我有两个数组,一个是选项卡,另一个是存储库。

我正在尝试根据存储库列表对选项卡数组进行排序。如果存储库名称与选项卡匹配,则应首先排序(基于原始数组),不匹配的选项卡名称应最后排序(根据原始数组)。

但是,我在下面尝试了,无法根据上述条件进行排序。

有人可以帮忙吗?

我希望该解决方案可以在 angular 8 中使用。

var tabs = ["Primary", "302-15", "152-88", "MEVCP"];  
// Imagine it's a tab names

var repositories = [
  {
    "repositoryGuid": "",
    "name": "Git Test 4",
    "description": "Git Description",
    "provider": "",
    "url": "",
    "modified": "2019-11-18T02:39:17.333",
    "modifiedBy": ""
  },
  {
    "repositoryGuid": "123",
    "name": "Primary",
    "description": "ITP Primary SQL Database",
    "provider": "",
    "url": "",
    "modified": "2019-06-06T00:00:00",
    "modifiedBy": ""
  },
  {
    "repositoryGuid": "456",
    "name": "MEVCP",
    "description": "GIT test repository",
    "provider": "",
    "url": "",
    "modified": "2019-09-30T16:01:47.17",
    "modifiedBy": ""
  },
  {
    "repositoryGuid": "679",
    "name": "GIT Test",
    "description": "GIT test repository",
    "provider": "",
    "url": "",
    "modified": "2019-11-15T21:26:22.27",
    "modifiedBy": ""
  },
  {
    "repositoryGuid": "591",
    "name": "ME-Cored-Convergence",
    "description": "ME-Core-Convergence",
    "provider": "",
    "url": "",
    "modified": "2019-09-30T15:38:46",
    "modifiedBy": ""
  }
];

const intersection = repositories.filter(element => tabs.includes(element.name));
console.log(intersection); // Getting matched values from tabs array

tabs.sort(function (a, b) {
  return intersection.indexOf(a.name) - intersection.indexOf(b.name);
});

console.log("after sorting", tabs);

预期的输出应该是

["Primary", "MEVCP", "302-15", "152-88"]

PS:所有其他不匹配的值应与原始数组在同一级别排序。

【问题讨论】:

  • "我希望该解决方案可以在 angular 8 中使用。" 这是一个纯 JS 问题,还是我遗漏了什么?
  • 可以像es6一样简单

标签: javascript angular sorting ecmascript-6 filter


【解决方案1】:

你可以用O(n)复杂度来实现这一点,如果你

  1. 首先获取所有现有存储库的集合,以便以后查找。
  2. 由于您还需要根据数组中的初始位置进行排序,因此您需要保留它。
    • 您可以获得每个数组的所有排序条件的 Map
  3. 最后根据repositories中的存在对tabs进行排序
    • 如果存在一个选项卡,则另一个不存在 - 将现有选项卡放在更高的位置
    • 如果两个选项卡都存在或不存在 - 根据位置排序

这是它的样子:

var tabs = ["Primary", "302-15", "152-88", "MEVCP"];  
// Imagine it's a tab names

var repositories = [ { "repositoryGuid": "", "name": "Git Test 4", "description": "Git Description", "provider": "", "url": "", "modified": "2019-11-18T02:39:17.333", "modifiedBy": "" }, { "repositoryGuid": "123", "name": "Primary", "description": "ITP Primary SQL Database", "provider": "", "url": "", "modified": "2019-06-06T00:00:00", "modifiedBy": "" }, { "repositoryGuid": "456", "name": "MEVCP", "description": "GIT test repository", "provider": "", "url": "", "modified": "2019-09-30T16:01:47.17", "modifiedBy": "" }, { "repositoryGuid": "679", "name": "GIT Test", "description": "GIT test repository", "provider": "", "url": "", "modified": "2019-11-15T21:26:22.27", "modifiedBy": "" }, { "repositoryGuid": "591", "name": "ME-Cored-Convergence", "description": "ME-Core-Convergence", "provider": "", "url": "", "modified": "2019-09-30T15:38:46", "modifiedBy": "" } ]; 

//1. create set
const set = new Set(repositories.map(repo => repo.name));

//2. create map with sorting data
const map = new Map(tabs
  .map((tab, index) => [
    tab,
    { index, exists: set.has(tab) }
  ]
))

//3. sort
tabs.sort((a, b) => {
  const tabA = map.get(a);
  const tabB = map.get(b);
  
  return (tabB.exists - tabA.exists) || 
    (tabA.index - tabB.index)
});

console.log("after sorting", tabs);

另一种方法是执行与链式操作等效的操作

  1. 获取套装
  2. 用与排序相关的数据丰富数组
  3. 排序
  4. 提取原始数组的数据

这里是实现:

var tabs = ["Primary", "302-15", "152-88", "MEVCP"];  
// Imagine it's a tab names

var repositories = [ { "repositoryGuid": "", "name": "Git Test 4", "description": "Git Description", "provider": "", "url": "", "modified": "2019-11-18T02:39:17.333", "modifiedBy": "" }, { "repositoryGuid": "123", "name": "Primary", "description": "ITP Primary SQL Database", "provider": "", "url": "", "modified": "2019-06-06T00:00:00", "modifiedBy": "" }, { "repositoryGuid": "456", "name": "MEVCP", "description": "GIT test repository", "provider": "", "url": "", "modified": "2019-09-30T16:01:47.17", "modifiedBy": "" }, { "repositoryGuid": "679", "name": "GIT Test", "description": "GIT test repository", "provider": "", "url": "", "modified": "2019-11-15T21:26:22.27", "modifiedBy": "" }, { "repositoryGuid": "591", "name": "ME-Cored-Convergence", "description": "ME-Core-Convergence", "provider": "", "url": "", "modified": "2019-09-30T15:38:46", "modifiedBy": "" } ]; 

//1. create the set
const set = new Set(repositories.map(repo => repo.name));

const sorted = tabs
  .map((tab, index) => ({ //2. enrich
    tab, 
    index, 
    exists: set.has(tab)
  }))
  .sort((a, b) => (b.exists - a.exists) || (a.index - b.index)) //3. sort
  .map(({tab}) => tab); //4. extract

console.log("after sorting", sorted);

【讨论】:

  • 感谢您的回答
【解决方案2】:

您可以在每次匹配时遍历repositoriessplice 选项卡,然后将结果与剩余项连接起来:

var tabs = ["Primary", "302-15", "152-88", "MEVCP"];  
// Imagine it's a tab names

var repositories = [
  {
    "repositoryGuid": "",
    "name": "Git Test 4",
    "description": "Git Description",
    "provider": "",
    "url": "",
    "modified": "2019-11-18T02:39:17.333",
    "modifiedBy": ""
  },
  {
    "repositoryGuid": "123",
    "name": "Primary",
    "description": "ITP Primary SQL Database",
    "provider": "",
    "url": "",
    "modified": "2019-06-06T00:00:00",
    "modifiedBy": ""
  },
  {
    "repositoryGuid": "456",
    "name": "MEVCP",
    "description": "GIT test repository",
    "provider": "",
    "url": "",
    "modified": "2019-09-30T16:01:47.17",
    "modifiedBy": ""
  },
  {
    "repositoryGuid": "679",
    "name": "GIT Test",
    "description": "GIT test repository",
    "provider": "",
    "url": "",
    "modified": "2019-11-15T21:26:22.27",
    "modifiedBy": ""
  },
  {
    "repositoryGuid": "591",
    "name": "ME-Cored-Convergence",
    "description": "ME-Core-Convergence",
    "provider": "",
    "url": "",
    "modified": "2019-09-30T15:38:46",
    "modifiedBy": ""
  }
];

let result = [];

for(let rep of repositories) {
   let index = tabs.indexOf(rep.name);
   if(index !== -1) {
      result.push(tabs[index]);
      tabs.splice(index, 1);
   }
}

result = [...result, ...tabs];

console.log(result);

【讨论】: