在不同文件的数组中查找重复名称

Posted

技术标签:

【中文标题】在不同文件的数组中查找重复名称【英文标题】:Find duplicate names within an array of different files 【发布时间】:2021-11-24 16:41:05 【问题描述】:

与我上面建议的用例有点不同。 我需要遍历并检查文件数组中的每个文件名,并将具有相同名称的文件推送到新数组中,以便稍后单独上传。

到目前为止,这是我的代码,我的条件检查肯定有问题,有人能看出我做错了什么吗?

filesForStorage = [
id: 12323, name: 'name', ...,
id: 3123, name: 'abc', ...,
id: 3213, name: 'name', ...,
...
]

    filesForStorage.map((image, index) => 
          for (let i = 0; i < filesForStorage.length; i++) 
            for (let j = 0; j < filesForStorage.length; j++) 
              if (
                filesForStorage[i].name.split(".", 1) ===.   //.split('.', 1) is to not keep in consideration the file extension
                filesForStorage[j].name.split(".", 1)
              ) 
                console.log(
                  "----FILES HAVE THE SAME NAME " +
                    filesForStorage[i] +
                    " " +
                    filesForStorage[j]
                );
              
            
          

【问题讨论】:

你能分享一下filesForStorage的演示数据吗?一个 sn-p 会很棒。 为什么要在Array.map中运行2个for循环? 当然,数组和文件是这样的:Array (10) 0 File id: 0.6385802192553822, preview: "blob:localhost:3000/c857aaa7-51dd-4d8a-b209-810b9eaf9d34", uniqueId: "8Am0GOPEwATyd0ZkSHlG", name: "background1. jpeg", lastModified: 1624555546000, ... 1 文件 live: true, id: 0.6403926850353915, preview: "blob:localhost:3000/e6db45de-cd66-408e-8c55-ac9a9968d504", uniqueId: "6hPqArZp1nNqruDIbh74", name: "image.gif", ... 2 File id : 0.5735947653890782, 预览: "blob:localhost:3000/697954be-50ee-46e6-ba38-8d6be54e7a9d", 名称: "background.png", ... , ...] 我正在映射,因为我在用于将每个文件发送到我的数据库的同一函数中执行此操作,我之前也可以这样做。 @Jacopo 请格式化它们并将它们添加到问题中 【参考方案1】:

使用map 而不返回任何内容会使它几乎毫无意义。您可以使用forEach,但是当您在其中使用双循环时,这同样毫无意义——这意味着您将在foreach(或您的情况下为map)循环一次,然后再循环两次以吸引眼球- 糟糕的表现。

您真正想做的是按name 对您的项目进行分组,然后选择任何包含超过 1 个元素的组

const filesForStorage = [
id: 12323, name: 'name',
id: 3123, name: 'abc',
id: 3213, name: 'name'
]

const grouped = Object.values(
  filesForStorage.reduce( (a,i) => 
    a[i.name] = a[i.name] || [];
    a[i.name].push(i);
    return a;
  ,)
);

console.log(grouped.filter(x => x.length>1).flat());

【讨论】:

干杯杰米克!欣赏答案! 此外,我可以在reduce中拼接(删除)原始数组中找到的文件吗? @Jacopo 只有一个条目的可以是grouped.filter(x =&gt; x.length == 0).flat() 根本不需要更改原始数组。 我建议使用Set 或Map 而不是数组【参考方案2】:

javascript 有几个执行“隐藏”迭代的函数。

Object.values 将遍历键值对对象并收集数组中的所有值 Array.prototype.reduce 将遍历数组并对每个元素执行计算,最后返回单个值 Array.prototype.filter 将遍历一个数组并收集所有对指定测试返回 true 的元素 Array.prototype.flat 将遍历一个数组,将每个元素连接到下一个元素,以创建一个新的扁平数组

所有这些方法都是浪费的,因为您可以使用单次遍历输入数组来计算重复的集合。此外,与 Set 或 Map 的 O(1) 性能相比,数组方法最多只能提供 O(n) 性能,这使得这种计算的数组选择非常糟糕 -

function* duplicates (files) 
  const seen = new Set()
  for (const f of files) 
    if (seen.has(f.name))
      yield f
    else
      seen.add(f.name, f)
  


const filesForStorage = [
  id: 12323, name: 'foo',
  id: 3123, name: 'abc',
  id: 3213, name: 'foo',
  id: 4432, name: 'bar',
  id: 5213, name: 'qux',
  id: 5512, name: 'bar',
]

for (const d of duplicates(filesForStorage))
  console.log("duplicate name found", d)
duplicate name found 
  "id": 3213,
  "name": "foo"

duplicate name found 
  "id": 5512,
  "name": "bar"

【讨论】:

【参考方案3】:

嵌套循环在性能上可能会非常昂贵,尤其是当您的数组有很多值时。这样的东西会好很多。

filesForStorage = [
   id: 12323, name: 'name' ,
   id: 3123, name: 'abc' ,
   id: 3213, name: 'name' ,
   id: 3123, name: 'abc' ,
   id: 3213, name: 'name' ,
   id: 3123, name: 'random' ,
   id: 3213, name: 'nothing' ,
]

function sameName() 
  let checkerObj = ;
  let newArray = [];

  filesForStorage.forEach(file => 
   checkerObj[file.name] = (checkerObj[file.name] || 0) + 1;
  );

  Object.entries(checkerObj).forEach(([key, value]) => 
    if (value > 1) 
      newArray.push(key);
    
  );

  console.log(newArray);



sameName();

【讨论】:

以上是关于在不同文件的数组中查找重复名称的主要内容,如果未能解决你的问题,请参考以下文章

按名称 Jquery 数组查找 id [重复]

如何在一个键值不同的php数组中查找和删除几乎重复的行?

如果对象数组中两个不同对象的两个键在JavaScript中相同,则通过键查找对象[重复]

查找接近重复记录的技术

为啥名称在我的数组中重复,我将如何获得一个 txt 文件进行排序

在数组中查找重复的条目