从列表中长期删除字符串中的单引号

2024-06-25 06:35:01 发布

您现在位置:Python中文网/ 问答频道 /正文

这一切都有点模糊,因为该计划是相当深入,但请坚持我,因为我会尽力解释它。我编写了一个程序,它接受.csv文件,并将其转换为MySQL数据库的INSERT INTO语句。例如:

ID   Number   Letter   Decimal   Random
0    1        a        1.8       A9B34
1    4        b        2.4       C8J91
2    7        c        3.7       L9O77

将导致插入语句,如:

INSERT INTO table_name ('ID' int, 'Number' int, 'Letter' varchar(). 'Decimal', float(), 'Random' varchar()) VALUES ('0', '1', 'a', '1.8', 'A9B34');

但是,并不是所有的.csv文件都有相同的列标题,但它们需要插入到同一个表中。对于没有特定列标题的文件,我想插入一个NULL值来显示这一点。例如:

假设第一个.csv文件,A包含以下信息:

^{pr2}$

第二个.csv文件,B有不同的列标题:

ID   Number   Letter   Decimal
0    3        x        5.6
1    8        y        4.8

在转换为INSERT语句并放入数据库后,理想情况下它应该如下所示:

ID   TableID   Number   Decimal   Letter   Random
0    A         1        1.8       NULL     A9B34
1    A         4        2.4       NULL     C8J91
2    B         3        5.6       x        NULL
3    B         8        4.8       y        NULL

现在我可能会开始失去你。

为了完成我需要的工作,我首先获取每个文件并创建一个主列表,其中包含.csv文件的列标题:

def createMaster(path):
    global master
    master = []
    for file in os.listdir(path):
        if file.endswith('.csv'):
            with open(path + file) as inFile:
                csvFile = csv.reader(inFile)
                col = next(csvFile) # gets the first line of the file, aka the column headers
                master.extend(col) # adds the column headers from each file to the master list
                masterTemp = OrderedDict.fromkeys(master) # gets rid of duplicates while maintaining order
                masterFinal = list(masterTemp.keys()) # turns from OrderedDict to list
    return masterFinal

它将从多个.csv文件中获取所有列标题,并按顺序将它们组合到一个主列表中,而不会出现重复项:

['ID', 'Number', 'Decimal', 'Letter', 'Random']

这为我提供了INSERT语句的第一部分。现在我需要将VALUES部分添加到语句中,因此我获取并列出每个.csv文件每行中的所有值的列表,一次一个。然后为该列的每个文件头创建一个临时列表,并将其与该列的所有文件头进行比较。然后它遍历主列表中的每一项,并尝试获取列列表中同一项的索引。如果在列列表中找到该项,则会将该项从同一索引的行列表中插入到临时列表中。如果找不到项,则将'NULL'插入临时列表中。一旦它完成了临时列表,它就会将这个列表转换成一个MySQL语法的字符串,并将其附加到一个.sql文件中以供插入。以下是代码中的相同想法:

def createInsert(inPath, outPath):
    for file in os.listdir(inpath):
        if file.endswith('.csv'):
            with open(inPath + file) as inFile:
                with open(outPath + 'table_name' + '.sql', 'a') as outFile:
                    csvFile = csv.reader(inFile)
                    col = next(csvFile) # gets the first row of column headers
                    for row in csvFile:
                        tempMaster = [] # creates a tempMaster list
                        insert = 'INSERT INTO ' + 'table_name' + ' (' + ','.join(master)+ ') VALUES ' # SQL syntax crap
                        for x in master:
                            try:
                                i = col.index(x) # looks for the value in the column list
                                r = row[i] # gets the row value at the same index as the found column
                                tempMaster.append(r) # appends the row value to a temporary list
                            except ValueError:
                                tempMaster.append('NULL') # if the value is not found in the column list it just appends the string to the row master list
                            values = map((lambda x: "'" + x.strip() + "'"), tempMaster) # converts tempMaster from a list to a string
                            printOut = insert + ' (' + ','.join(values) + '):')
                            outFile.write(printOut + '\n') # writes the insert statement to the file

现在是时候提问了。

此程序的问题是createInsert()从tempMaster列表中获取所有行值,并通过以下行将它们与'标记连接起来:

values = map((lambda x: "'" + x.strip() + "'"), tempMaster)

除了MySQL希望插入NULL值而只插入NULL值而不是{},这一切都很好。在

如何获取已组装的行列表并搜索'NULL'字符串并将其更改为NULL

我有两个不同的想法:

我可以沿着这些行来做一些事情,从'标记中提取NULL字符串并将其替换到列表中。在

def findBetween(s, first, last):
    try:
        start = s.index(first) + len(first)
        end = s.index(last, start)
        return s[start:end]
    except ValueError:
        print('ERROR: findBetween function failure.')

def removeNull(aList):
    tempList = []
    for x in aList:
        if x == 'NULL':
            norm = findBetween(x, "'", "'")
            tempList.append(norm)
        else:
            tempList.append(x)
    return tempList

或者我可以将NULL值添加到列表中,而不首先添加'这在createInsert()函数中。

^{9}$

但是我认为这两种方法都不可行,因为它们会显著降低程序的速度(对于较大的文件,它们会引发MemoryError)。因此,我征求你的意见。我很抱歉,如果这是混淆或难以理解。如果是这样的话,请让我知道我能做些什么来让它更容易理解,并祝贺你做到了这一点!在


Tags: 文件csvthetoinmaster列表for
2条回答

我检查了你的要求,我发现你的目录里有多个CSV。这些csv有动态列。我的方法是创建所有列的静态列表

staticColumnList = ["ID","TableID","Number","Decimal","Letter","Random"]

现在,在读取文件时,获取头行并为相应列的元组创建一个临时列表,例如

[(ID, column no in csv), (TableID, 'A' - File Name), (Number, column no in csv) etc...]

如果csv中没有列,那么将x放在("Letter", x)中。现在对每一行创建一个循环,并指定或拾取值,例如这:在

wholeDataList = []
rowList = []
for column in staticColumnList:
    if int of type(column[1]):
      rowList.append("'"+str(rowCSV[column[1]])+"'")
    elif 'X' == column[1]:
      rowList.append('null')
    else:
      rowList.append("'"+column[1]+"'")


wholeDataList.append("("+",".join(rowList)+")")

最后你准备好了陈述,比如这:在

^{pr2}$

而不是

values = map((lambda x: "'" + x.strip() + "'"), tempMaster)

把这个放进去

^{pr2}$

编辑

谢谢你接受/支持我的简单技巧,但我不确定这是最佳的。 在一个更全局的范围内,您可以避免这种map/lambda的东西(除非我遗漏了什么)。
                for row in csvFile:
                    values = [] # creates the final list
                    insert = 'INSERT INTO ' + 'table_name' + ' (' + ','.join(master)+ ') VALUES ' # SQL syntax crap
                    for x in master:
                        try:
                            i = col.index(x) # looks for the value in the column list
                            r = row[i] # gets the row value at the same index as the found column
                            value.append("'"+r.strip()+"'") # appends the row value to the final list
                        except ValueError:
                            value.append('NULL') # if the value is not found in the column list it just appends the string to the row master list

{cd1>你就可以节省内存了。在

相关问题 更多 >