如何使用 reduce 属性 和 return 新数组 objects 对数组中的项目进行分组

How to group items in an array by property using reduce and return an array of new objects

考虑这个 object 的数组:

const relatedSites = [
  {
    "SubdomainName": "client1",
    "ClientName": "Eastern Region",
    "ClientAlias": "eastern-region"
  },
  {
    "SubdomainName": "client1",
    "ClientName": "City of Knox",
    "ClientAlias": "knox"
  },
  {
    "SubdomainName": "client2",
    "ClientName": "Eastern Region",
    "ClientAlias": "eastern-region"
  },
  {
    "SubdomainName": "client2",
    "ClientName": "City of Knox",
    "ClientAlias": "knox"
  }
]

我想通过“SubdomainName”属性 和 return 一组使用 reduce 的新制作的 object 对它们进行分组,所以我得到了这个结果:

[
  {
    "title": "client1",
    "links": [
      {
        "url": "https://client1.com/eastern-region",
        "displayText": "Eastern Region"
      },
      {
        "url": "https://client1.com/knox",
        "displayText": "City of Knox"
      }
    ]
  },
  {
    "title": "client2",
    "links": [
      {
        "url": "https://client2.com/eastern-region",
        "displayText": "Eastern Region"
      },
      {
        "url": "https://client2.com/knox",
        "displayText": "City of Knox"
      }
    ]
  }
]

到目前为止,这是我的解决方案,但我认为它看起来有点笨拙,有没有更有效的方法?如果我没有按标题找到它,我不喜欢创建新组的方式,而且根据是否找到它的索引将组推到数组中感觉不整洁。有没有更优雅的方式达到同样的效果?

  const groupRelatedSites = (groups, item) => {
    const group = groups.find(gp => gp.title === item.SubdomainName) || { title: item.SubdomainName, links: [] };
    const index = groups.findIndex(group => group.title === item.SubdomainName);
    const link = { url: `https://${item.SubdomainName}.com/${item.ClientAlias}`, displayText: item.ClientName };
    group.links = [...group.links, link];

    if (index === -1) {
      groups.push(group);
    } else {
      groups[index] = group;
    }
    return groups;
  };

  const grouped = relatedSites.reduce(groupRelatedSites, []);

const relatedSites = [{"SubdomainName": "client1","ClientName": "Eastern Region","ClientAlias": "eastern-region"},{"SubdomainName": "client1","ClientName": "City of Knox","ClientAlias": "knox"},{"SubdomainName": "client2","ClientName": "Eastern Region","ClientAlias": "eastern-region"},{"SubdomainName": "client2","ClientName": "City of Knox","ClientAlias": "knox"}];

const out = relatedSites.reduce((a, b) => {
  const title = b.SubdomainName;
  let obj = a.find(x => x.title === title);
  if (!obj) a.push({
    title: title,
    links: [{ 
      url: `https://${title}.com/${b.ClientAlias}`,
      displayText: b.ClientName,
    }] });
  else obj.links.push({
    url: `https://${title}.com/${b.ClientAlias}`,
    displayText: b.ClientName,
  });
  return a;
}, []);

console.log(out);

你已经很接近了,但让事情变得比需要的更复杂了

const relatedSites = [{
    "SubdomainName": "client1",
    "ClientName": "Eastern Region",
    "ClientAlias": "eastern-region"
  },
  {
    "SubdomainName": "client1",
    "ClientName": "City of Knox",
    "ClientAlias": "knox"
  },
  {
    "SubdomainName": "client2",
    "ClientName": "Eastern Region",
    "ClientAlias": "eastern-region"
  },
  {
    "SubdomainName": "client2",
    "ClientName": "City of Knox",
    "ClientAlias": "knox"
  }
]

let data = relatedSites.reduce((b, a) => {
    let ind = b.findIndex(e => e.title === a.SubdomainName)
    let obj = {
      url: "https://" + a.SubdomainName + ".com/" + a.ClientAlias,
      displayText: a.ClientAlias
    };
    if (ind > -1) {
      b[ind].links.push(obj)
    } else {
      b.push({
        "title": a.SubdomainName,
        "links": [obj]
      })
    }
    return b;
  }, []);

console.log(data)

您应该可以使用 reduce 在几行内完成此操作,我们使用子域名作为键创建一个映射,然后我们将使用 Object.values 将结果对象转换为数组。

例如:

const relatedSites = [ { "SubdomainName": "client1", "ClientName": "Eastern Region", "ClientAlias": "eastern-region" }, { "SubdomainName": "client1", "ClientName": "City of Knox", "ClientAlias": "knox" }, { "SubdomainName": "client2", "ClientName": "Eastern Region", "ClientAlias": "eastern-region" }, { "SubdomainName": "client2", "ClientName": "City of Knox", "ClientAlias": "knox" } ]; 

const result = Object.values(relatedSites.reduce((acc, el) => { 
    acc[el.SubdomainName] = acc[el.SubdomainName] || { title: el.SubdomainName, links: [] };
    acc[el.SubdomainName].links.push({ url: `https://${el.SubdomainName}.com/${el.ClientAlias}`, displayText: el.ClientName });
    return acc;
}, {}))

console.log(result)