Board logo

标题: [问题求助] PowerShell怎样将csv中大致重复的项另存为新csv文件 [打印本页]

作者: 5i365    时间: 2022-1-6 18:42     标题: PowerShell怎样将csv中大致重复的项另存为新csv文件

如何用powershell将csv文件中大致重复的项另存为新csv文件,
例如下面的这个csv文件, 歌手和歌名并非完全重复

------------------------------------------------------------------------------
排序,语言,歌手,歌名
66,国语,安静,红颜知己
67,国语,韩可可,错位时空 (女版)
68,国语,于洋,望爱却步
75,国语,胡小斐,无药可愈
76,国语,en,嚣张
565,国语,韩可可(3),错位时空
566,国语,杜宣达,原来我从未忘记你
567,国语,悦开心,别想他
568,国语,新乐尘符,123我爱你

作者: 5i365    时间: 2022-1-7 12:25

这个有解吗?  一点头绪也没有
作者: went    时间: 2022-1-7 13:05

只根据括号内容(.*?)区分就很简单
输入0.csv  输出1.csv
  1. #&cls&@ cd /d "%~dp0" & powershell -c "Get-Content '%~0' | Out-String | Invoke-Expression" & pause&exit
  2. $set = @{}
  3. $content = Get-Content '0.csv' -Encoding UTF8
  4. $content | foreach {
  5.     $arr = $_ -split ','
  6.     $a = ($arr[2] -replace '\(.*?\)','').Trim() + ',' + ($arr[3] -replace '\(.*?\)','').Trim()
  7. if($set.$a -eq $null){
  8. $set.$a = $_
  9. } else {
  10. $set.$a = $set.$a + "`n" + $_
  11. }
  12. }
  13. $set.Values | Where-Object { ($_ -split '\n').Count -gt 1 } | Out-File '1.csv'
复制代码

作者: 5i365    时间: 2022-1-7 13:38

本帖最后由 5i365 于 2022-1-7 13:44 编辑

回复 3# went


    感谢帮忙, 我现在想了一个逻辑,
如果歌手中有连续的三个字重复【即csv文件第三行】, 同时歌名中有连续的三个字重复【即csv文件第四行】, 此时就算满足条件, 最好有个变量, 我可以修改连续文字的数量
还有个可能的情况是,不只两行中的有重复的情况, 还有可能是三行或N行中有上面描述的重复情况
作者: went    时间: 2022-1-7 14:10

回复 4# 5i365


    没有测试大量数据
  1. cls
  2. #函数 获取两个字符串最大相同字符个数
  3. function Get-SameNum([string]$str1,[string]$str2){
  4.     $max = 0
  5.     $len = 0
  6.     if($str1.Length -le $str2.Length){
  7.         $len = $str1.Length
  8.         $s1 = $str1
  9.         $s2 = $str2
  10.     } else {
  11.         $len = $str2.Length
  12.         $s1 = $str2
  13.         $s2 = $str1
  14.     }
  15.     for($i = 0;$i -lt $len; $i++){
  16.         for($j = 1; $j -lt $len-$i+1; $j++){
  17.             $s_t = $s1.Substring($i,$j)
  18.             if($s2.IndexOf($s_t) -ne -1){
  19.                 if($s_t.Length -gt $max){
  20.                     $max = $s_t.Length
  21.                 }
  22.             }
  23.         }
  24.     }
  25.     return $max
  26. }
  27. #阈值设置 >=
  28. $m1 = 3
  29. $m2 = 3
  30. #比较并输出
  31. $content = Get-Content '0.csv' -Encoding UTF8
  32. &{
  33.     $content | foreach {
  34.         $__ = $_
  35.         $content | Where-Object { $_ -ne $__} | foreach {
  36.             $arr1 = $__ -split ','
  37.             $arr2 = $_ -split ','
  38.             $a = Get-SameNum -str1 $arr1[2] -str2 $arr2[2]
  39.             $b = Get-SameNum -str1 $arr1[3] -str2 $arr2[3]
  40.             if($a -ge $m1 -and $b -ge $m2){
  41.                 $__
  42.             }
  43.         }
  44.     }
  45. } | Out-File '1.csv'
复制代码

作者: 5i365    时间: 2022-1-7 18:52

回复 6# xczxczxcz


    感谢分享, 执行后,生成的文件为空, 请问如何使用?
作者: 5i365    时间: 2022-1-7 19:02

本帖最后由 5i365 于 2022-1-7 19:11 编辑

回复 5# went


    如果csv有1000条,不知是对比时间太漫长还是怎么一直不能结束, 然后我就手动关闭了,生成的结果中,还是有问题,相同的并没有上下显示在相邻行
作者: xczxczxcz    时间: 2022-1-7 19:54

回复 7# 5i365

不会用那就不用,你还是使用低效版吧。

实测上万条数据也就弹指一挥间完成,稍为改一下就是高效率了。

禁止套娃。
作者: went    时间: 2022-1-7 20:29

回复 7# 5i365


    可以传csv附件给我测试优化
作者: 5i365    时间: 2022-1-8 09:42

本帖最后由 5i365 于 2022-1-8 09:51 编辑

回复 8# xczxczxcz


大侠, 侠气凛然, 着实让从人佩服!!!

在下不才,  昨晚真是试了很多次没有结果, 到头了没看懂你写的怎么用,

论坛本来就是个学习的地方, 但凡路过的坛友, 学习一翻你的代码, 更显你的豪气, 更多一份敬佩!!

但是刚才一找, 代码删了, 不见了, 那真就是在俺一个入门者面前耍一下大刀, 炫技了一翻, 没有任何意义

无论如何, 大侠能抽自己的时间和精力加入到处理这个论坛问题的队伍中来, 还是非常感谢的

不明白什么叫 禁止套娃, 百度了一下刚懂, 现在娃没有了, 是不是大家可以随便套了?
作者: 5i365    时间: 2022-1-8 10:04

回复 9# went


    感谢回复, 已传, 大侠认真的态度让人钦佩, 宛若论坛中的一股清流!
作者: went    时间: 2022-1-8 13:04

本帖最后由 went 于 2022-1-8 13:09 编辑

回复 11# 5i365
还是 输入0.csv 输出1.csv
  1. #&cls&@powershell -c "Get-Content '%~0' | Select-Object -Skip 1 | Out-String | Invoke-Expression" &pause&exit
  2. cls
  3. #函数 获取两个字符串最大相同字符个数
  4. function Get-SameNum([string]$str1,[string]$str2){
  5.     $max = $len = 0
  6.     if($str1.Length -le $str2.Length){
  7.         $len = $str1.Length; $s1 = $str1; $s2 = $str2
  8.     } else {
  9.         $len = $str2.Length; $s1 = $str2; $s2 = $str1
  10.     }
  11.     for($i = 0;$i -lt $len; $i++){
  12.        if($len-$i -le $max){ break; }
  13.         for($j = 1; $j -lt $len-$i+1; $j++){
  14.             $s_t = $s1.Substring($i,$j)
  15.             if($s2.IndexOf($s_t) -ne -1){
  16.                 if($s_t.Length -gt $max){ $max = $s_t.Length }
  17.             }
  18.         }
  19.     }
  20.     return $max
  21. }
  22. #阈值设置 >=
  23. $m1 = 3
  24. $m2 = 3
  25. #比较并输出
  26. $list = [System.Collections.ArrayList](Get-Content '0.csv' -Encoding UTF8 | Select-Object -Skip 1)
  27. &{
  28.     &{
  29.         $list | Sort-Object {
  30.             $arr = $_ -split ','
  31.             ($arr[2] -replace '[\(\[\{].*[\)\]\}]',''),
  32.             ($arr[3] -replace '[\(\[\{].*[\)\]\}]',''),
  33.             ($arr[0])
  34.         } | foreach {
  35.             $line = $_
  36.             $singer = ($_ -split ',')[2]
  37.             $song = ($_ -split ',')[3]
  38.             if($last_line -ne $null){
  39.                 $a = Get-SameNum -str1 $singer -str2 $last_singer
  40.                 if($a -ge $m1){
  41.                     $b = Get-SameNum -str1 $song -str2 $last_song
  42.                     if($b -ge $m2){
  43.                         if(!$last){ $last_line; $last = $true}
  44.                         $_
  45.                     }
  46.                 } else {
  47.                     $last = $false
  48.                 }
  49.             }
  50.             $last_line = $line
  51.             $last_singer = $singer
  52.             $last_song = $song
  53.         }
  54.     }
  55. } | Out-File '1.csv'
复制代码

作者: 5i365    时间: 2022-1-8 13:51

回复 12# went


    感谢, 刚才试了一下, 得到下面的结果:

但有些项不应输出,例如;
795和534, 562和578, 851和501, 都是两首歌, 是同一歌手唱

前两组的输出是对的

感觉现在对比的逻辑是: 要先排除歌名中的括号中的内容后再对比

------------------------------------------------------
546,国语,Bomb比尔,0222心动-比尔的歌
407,国语,Bomb比尔,1022-比尔的歌
67,国语,韩可可,错位时空 (女版)
565,国语,韩可可(3),错位时空
795,粤语,亮声open,多年以后 (粤语版)
534,粤语,亮声open,无人与我 (粤语版)
562,国语,刘大壮,我很好 (吉他版)
578,国语,刘大壮,一吻天荒 (吉他版)
851,国语,杨冰心,红尘谁不是过客 (女版)
501,国语,杨冰心,学会爱自己 (女版)
作者: went    时间: 2022-1-8 14:17

回复 13# 5i365


    37.38行修改下
  1. $singer = ($_ -split ',')[2] -replace '[\(\[\{].*[\)\]\}]',''
  2. $song = ($_ -split ',')[3] -replace '[\(\[\{].*[\)\]\}]',''
复制代码





欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2