从CSV中删除重复字符串

Tdignan87.

众所周知的成员
加入
2019年7月8日
消息
95
编程经验
Beginner
你好,
我有来自我们的ERP系统的CSV文件,尽管系统有一个错误(等待它是固定的),那么它偶尔会发送一个文件,其中包含具有重复行的CSV文件,然后与我们的其他系统导致混乱它进口到。
然而,我应该在几周内修复ERP;

如何创建一个简单的控制台文件,该文件检查任何CSV的文件夹,并读取文件并检查第二行是否与前两个文本行匹配;如果是这样,它只需删除最后一行。
下面的CSV示例
"P0755","R190830022","2021-08-30","POSITIVE RELEASE",57.000,"TRUE"
"P0755","R190830022","2021-08-30","POSITIVE RELEASE",14.500,"TRUE"

我基本上希望应用程序将第二行作为前4个值删除"" match.

任何帮助都会受到理解或例子。
 

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
That's no bother. Glad to help, and if you want to work towards simplifying the code, you can use the two lines i last gave you and change 细绳[] csvReader, to a hashset and use lines 44 with a little tweak to remove the duplicates. You'd do the whole lot in about 5 lines or so. ;)
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,903
地点
切萨皮克,va.
编程经验
10+
如果您相信Linq,这是一种替代方法:

C#:
class RowComparer : IEqualityComparer<string>
{
    public bool Equals(string x, string y) => GetHashCode(x) == GetHashCode(y);

    public int GetHashCode(string obj)
    {
        //$ TODO: need to replace this parsing with more robust parsing to handle quotes
        string key = obj?.Split(',')
                        ?.Skip(1)
                        ?.FirstOrDefault();
        return key?.GetHashCode() ?? 0;
    }
}
:

file.writeAlllines(tempfilename,
                  File.ReadLines(OriginalFileName)
                      .Distinct(new RowComparer()));
file.replace(tempfilename,worialfilename,null);
file.delete(tempfilename);

:

注意:上面未经​​测试的代码,它只是我在等待构建完成时在键盘上设计。
 

Tdignan87.

众所周知的成员
加入
2019年7月8日
消息
95
编程经验
Beginner
很酷,我会玩它。
现在说我想
1.删​​除重复项,但将它们移动到单个CSV文件中 :) (只是复制品)。什么是最好的方法?
 

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
使用您拥有的内容并学会编辑它。看起来很好地了解了重复处理的位置。然后是在文件编写的读写母体。

@skydiver 不确定它是否是因为我是移动的,但这看起来像很多文字。再次看,它可以缩短。将文件行读取到列表中,除了与LINQ的重复行和空行

从手机回复
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,903
地点
切萨皮克,va.
编程经验
10+
No need to read into a list. File.ReadLines() returns an IEnumerable<string>. File.WriteAllLines() also takes an IEnumerable<string>. All that is needed is a way to find the unique lines. Thate is where the LINQ Distinct() extension come in. It does all the magic you did with your HashSet in your original code (in fact if you look at the reference sources, it also uses a HashSet. All that is missing is to be able to tell Distinct() how to compare two different lines to see if they are the same or different. That is where the RowComparer which implements the IEqualityComparer comes in. This is what does the line parsing and pulls out the second column value and checks for equality.
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,903
地点
切萨皮克,va.
编程经验
10+
在看到我的比较之后,以及Jon Skeet的比较,我想出了像这种混合的东西:
C#:
班级比较<T, TKey> : IEqualityComparer<T>
{
    Func<T, TKey> _getKey;

    public Comparer(Func<T, TKey> getKey) => _getKey = getKey;
    公共BOOL等于(t x,t y)=>_getkey(x)== _getkey(y);
    public int gethashcode(t obj)=>_getkey(obj).gethashcode();
}

:
var padmer = new passper(r => r.Split(',')
                                  .ementatordfault(1)
                                  ?? "");
file.writeAlllines(tempfilename,
                   File.ReadLines(OriginalFileName)
                       。暗星(比较));
file.replace(tempfilename,worialfilename,null);
file.delete(tempfilename);
:

再次,未经测试的代码。只是在键盘上涂鸦。
 

Tdignan87.

众所周知的成员
加入
2019年7月8日
消息
95
编程经验
Beginner
class Comparer<T, TKey> : IEqualityComparer<T>
{
Func<T, TKey> _getKey;

public Comparer(Func<T, TKey> getKey) => _getKey = getKey;
公共BOOL等于(t x,t y)=>_getkey(x)== _getkey(y);
public int gethashcode(t obj)=>_getkey(obj).gethashcode();
}

:
var padmer = new passper(r => r.Split(',')
.ementatordfault(1)
?? "");
file.writeAlllines(tempfilename,
File.ReadLines(OriginalFileName)
。暗星(比较));
file.replace(tempfilename,worialfilename,null);
file.delete(tempfilename);
:
嗨Skydiver
我把它粘贴到控制台中,但它都是红色的。
我在哪里出错?请原谅我的愚蠢。

1570786308185.png.
 

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
在看到我的比较之后,以及Jon Skeet的比较,我想出了像这种混合的东西:
我仍然愿意使用GroupBy,选择,不同。如果通过任何手段,我可​​以避免写一个比较,我会。

每个人都是我猜的。
 

Tdignan87.

众所周知的成员
加入
2019年7月8日
消息
95
编程经验
Beginner
对不起 - 我只是在学习,我真的很挣扎! :(
这是我的代码。我需要重复的行删除并进入自己的单独的CSV文件,每个复制。一整天都在努力尝试,但我只是无法得到它。

这是我的代码
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace CSVRemoveDuplicates
{
 
        class Program
        {
            static string pathToFolder = @"C:\Users\tdignan\Documents\CSV TEST";
            private static void Main(string[] args)
            {
                // Console.WriteLine("Press Ctrl+V to paste in your path and press enter key :");
                /* After you Ctrl+V, and hit enter, pathToFile will be set to the directory of your CSV files */
                // pathToFolder = Console.ReadLine();
                DirectoryInfo directory = new DirectoryInfo(pathToFolder);
                foreach (FileInfo file in directory.GetFiles("*.csv"))
                {
                    RemoveDuplicates_InEachFile(file.FullName, file.Name);
                }
            }
            private static void RemoveDuplicates_InEachFile(string pathToFile, string filename)
            {
                // Below was put into file incase wanted CSV to go to a seperate directory. Easier if it is is within the same directory.
                string pathtoFile2 = @"C:\Users\tdignan\Documents\CSV TEST\STOCKRD" + DateTime.Now.ToFileTime() + ".csv";

                HashSet<string> hashSet = new HashSet<string>();
                /* Above are self explanatory, while below csvReader creates an array of strings from all lines in the file */


                IEnumerable<string> eachBlankLine = File.ReadAllLines(pathToFile).Where(emptyLine => !string.IsNullOrWhiteSpace(emptyLine));
                File.WriteAllLines(pathToFile, eachBlankLine);
                string[] csvReader = File.ReadAllLines(pathToFile);
                /* Loop the string array of lines */
                foreach (string line in csvReader)
                {
                    /* Split at second comma, by skipping the first one */
                    string partB = line.Split(',').Skip(1).FirstOrDefault();
                    bool hasText = hashSet.Any(Func_Partial => Func_Partial.Contains(partB));
                    if (hasText == false)
                    {
                        /* If it isn't added, we will add it below */
                        hashSet.Add(line);



                        /* Next we add line to the hash set */
                    }
                    else
                    {


                    }
                }
            /* Delete the file, and recreate it by appending it */

            //   File.Delete(pathToFile);
            //File.Delete(pathToFile);
            File.Delete(pathToFile);
            File.WriteAllLines(pathtoFile2, eachBlankLine);
          
            
      


          
            hashSet.ToList().ForEach(func_line => File.AppendAllText(pathToFile, string.Concat(func_line, Environment.NewLine)));
            
            // System.IO.File.WriteAllText(pathToFile, pathToFile);

            /* Lastly write the file back with only the entries we added, and no duplicates */
        }
        }
    }
 

Tdignan87.

众所周知的成员
加入
2019年7月8日
消息
95
编程经验
Beginner
我已经设法让它创建一个单独的CSV文件,但如果没有重复,它仍然会创建一个新的CSV文件,无论如何,无论其复制还是不可分得的,无论如何,无论如何都有数据。
代码移动重复,但也可以在原始文件中保持重复。
我需要它来删除原始文件中的重复,并为其不为任何记录创建任何新的CSV文件(如果没有重复)

干杯!
谢谢你的耐心!
 

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
我没有看到你是如何搞定的那个代码,即使是关于......无论如何的评论,也是如此,试试这个。我刚刚快速地写了它,我尚未测试它,但它应该工作,它还会在从原始目录中读取文件的副本文件夹中存储您的副本。请注意,如果文件存在,则不会覆盖它们。 :
C#:
        const string pathToFolder = @"C:\Users\user\Downloads\CSV Script\";
        const string pathNewDir = "Copies";
        private static void Main(string[] args)
        {
            DirectoryInfo directory = new DirectoryInfo(pathToFolder);
            FileInfo[] array = directory.GetFiles("*.csv");
            for (int i = 0; i < array.Length; i++)
            {
                FileInfo file = array[i];
                RemoveBlanks_InEachFile(file.FullName, Path.Combine(pathToFolder, pathNewDir, file.Name));
            }
        }
        private static void RemoveBlanks_InEachFile(string pathToFile, string pathOfCopies)
        {
            var existingPath = Path.GetDirectoryName(pathOfCopies);
            if (!Directory.Exists(existingPath))
                Directory.CreateDirectory(existingPath);
            IEnumerable<string> nonBlankLine = File.ReadAllLines(pathToFile).Where(nonEmptyLine => !string.IsNullOrWhiteSpace(nonEmptyLine));
            AddNon_Duplicated(nonBlankLine, pathOfCopies, null);
        }

        private static void AddNon_Duplicated(IEnumerable<string> nonBlankLine, string pathOfCopies, HashSet<string> hashSet_Filter)
        {
            hashSet_Filter = new HashSet<string>();
            foreach (var non_Duplicate in from string line in nonBlankLine
                                          let partB = line.Split(',').Skip(1).FirstOrDefault()
                                          let hasText = hashSet_Filter.Any(Func_Partial => Func_Partial.Contains(partB))
                                          where hasText == false
                                          select line)
            {
                hashSet_Filter.Add(non_Duplicate);
            }
            Write_IEnumerableValues(pathOfCopies, hashSet_Filter);
        }
        private static void Write_IEnumerableValues(string writeTo, IEnumerable<string> newValues)
        {
            File.WriteAllLines(writeTo, newValues);
        }
我会假设您使用的其他其他应用程序。导入这些新的CSV文件后,您将遍历目录并删除每个文件。
 
Last edited:

Tdignan87.

众所周知的成员
加入
2019年7月8日
消息
95
编程经验
Beginner
谢谢
我需要它删除从原始文件中删除重复记录,否则ERP系统将从原始文件处理事务;还有新的创造。
如果文件中没有重复,我需要它也不会创建第二个文件。
 

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
我这样做是这样的,因为将重复添加到新文件并没有意义。如果您将它们导入另一个系统,为什么需要重复的值?

您开始询问如何删除/删除重复项,然后再次询问将它们添加到新文件中。始终在开放的线程帖子中完全想要的,而不是改变主意。
好的,你可以拥有它。您更喜欢新文件或删除第二行吗?
是的,请删除很好。
如同引用,这不是你开始的要求。如果我最初被误解,我很抱歉,但这是改变主意的麻烦,或者从Get-Go完全谈论足够的描述。
我需要重复的行删除并进入自己单独的CSV文件
I deliberately compartmentalised the latest code into methods since your last attempt is all messed up, and so you can see where the work is being done. And if you want the duplicates only, you can acquire them at : foreach (var non_Duplicate in from string line in nonBlankLine, and pass them onto your writing method private static void Write_IEnumerableValues with the path(s) you want to use. You can extend the method to accommodate another string to accept a second path to write for your duplicates file path, and also add an additional IEnumerable<string>为您的复制品集合。

考虑一下;如果我给出了什么,我们已经采取了从CSV中排除未重复值的所有行,您认为您现在需要更改以仅获取重复值?
 
最佳 底部