You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用JS的Reduce函数对数组中同名对象分组?

如何用reduce合并同名的文档列表项?

我有一个对象数组,目前通过filter和map进行筛选与渲染,代码如下:

const countries = [
    "de",
    "fr",
    "nl"
];


const renderDocItem = (doc, country) => {
    return (
        <li className="tabsLi" key={doc._id}>
            <div className="d-flex w-75 justify-content-between">
                <div>
                    {doc.name}
                    <br />
                    <span className="filename">{doc.filename}</span>
                </div>
                <div>
                    {doc.master ? (
                        <img className="flag" src={en} />
                    ) : (
                        <img
                            className="flag"
                            src={objectOfCountries[country]}
                        />
                    )}
                    <span className="action">
                        [
                        <a href="#" onClick={() => view(doc, "view")}>
                            view
                        </a>
                        ,{" "}
                        <a href="#" onClick={() => view(doc, "edit")}>
                            edit
                        </a>
                        ]
                    </span>
                </div>
            </div>
        </li>
    );
};

const renderDocsPerCountry = (docs, country, category) => {
    const filteredDocs = docs.filter((doc) => {
        return doc.countries.includes(country) && doc.category == category;
    });
    const renderedDocs = filteredDocs.map((doc) => {
        return renderDocItem(doc, country);
    });
    console.log(renderedDocs);
    return renderedDocs;
};

<ul>{renderDocsPerCountry(docs, country, "xxx")}</ul>

这段代码会生成按“xxx”分类、按国家分组的列表项。问题在于部分对象拥有相同的name属性但所属国家不同,我希望将同名的对象进行分组合并。

当前输出:

<ul>
<li>Name1, filename1, country1, link</li>
<li>Name1, filename2, country2, link</li>
<li>Name3, filename3, country3, link</li>
</ul>

期望输出:

<ul>
<li>Name1, filename1/filename2, country 1 - link / country 2 - link</li>
<li>Name3, filename3, country3, link</li>
</ul>

请问对应的reduce函数应该如何编写?


解决方案

你可以通过reduce先按name对过滤后的文档进行分组,把同一名称下的文档信息整合,再渲染合并后的列表项:

  1. 修改renderDocsPerCountry函数,整合筛选、分组与渲染逻辑:
const renderDocsPerCountry = (docs, country, category) => {
    // 筛选符合分类与国家条件的文档
    const filteredDocs = docs.filter(doc => 
        doc.countries.includes(country) && doc.category === category
    );

    // 用reduce按name分组,聚合文件名和文档数据
    const groupedDocs = filteredDocs.reduce((acc, doc) => {
        const existingGroup = acc.find(group => group.name === doc.name);
        if (existingGroup) {
            // 已有同名分组,追加数据
            existingGroup.filenames.push(doc.filename);
            existingGroup.items.push(doc);
        } else {
            // 无同名分组,创建新分组
            acc.push({
                name: doc.name,
                filenames: [doc.filename],
                items: [doc]
            });
        }
        return acc;
    }, []);

    // 渲染合并后的列表项
    return groupedDocs.map(group => (
        <li className="tabsLi" key={group.name}>
            <div className="d-flex w-75 justify-content-between">
                <div>
                    {group.name}
                    <br />
                    <span className="filename">{group.filenames.join('/')}</span>
                </div>
                <div>
                    {/* 遍历分组内的所有文档,渲染对应的标识和操作链接 */}
                    {group.items.map((item, idx) => (
                        <span key={idx} style={{ marginRight: '12px' }}>
                            {item.master ? (
                                <img className="flag" src={en} />
                            ) : (
                                <img className="flag" src={objectOfCountries[country]} />
                            )}
                            <span className="action">
                                [
                                <a href="#" onClick={() => view(item, "view")}>view</a>
                                ,{" "}
                                <a href="#" onClick={() => view(item, "edit")}>edit</a>
                                ]
                            </span>
                            {/* 非最后一项添加分隔符 */}
                            {idx < group.items.length - 1 && ' / '}
                        </span>
                    ))}
                </div>
            </div>
        </li>
    ));
};
  1. 核心逻辑说明:
  • reduce的作用是将相同name的文档聚合为一个分组对象,保存名称、所有关联文件名,以及完整的文档数据(用于后续渲染操作链接和国家标识)
  • 渲染阶段,将同一分组的文件名用/拼接,同时遍历分组内的每个文档,渲染对应的国家标识和操作链接,并用/分隔不同国家的操作区域

这样就能实现你需要的同名项合并效果。


内容的提问来源于stack exchange,提问作者Eric Mitjans

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 01:07:49