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

时间:2016-08-02 17:31:30

标签: python mysql python-3.x csv

这有点模糊,因为该程序相当深入,但坚持我,因为我会尽力解释它。我编写了一个程序,它接受.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 包含以下信息:

ID   Number   Decimal   Random
0    1        1.8       A9B34
1    4        2.4       C8J91

第二个.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

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

为了完成我需要的工作,我首先获取每个文件并创建所有 {@ 1}}文件的列标题的主列表:

.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插入临时列表中。完成临时列表后,它会将列表转换为正确的MySQL语法字符串,并将其附加到'NULL'文件以进行插入。这是代码中的相同想法:

.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 从tempMaster列表中获取所有行值,并通过以下行与createInsert()标记连接:

'

这一切都很好,花花公子除了之外,MySQL希望插入values = map((lambda x: "'" + x.strip() + "'"), tempMaster) 个值而不是NULL而不是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()

但是我认为这些都不可行,因为它们会大大降低程序的速度(使用较大的文件会引发for x in tempMaster: if x == 'NULL': value = x tempMaster.append(value) else: value = "'" + x + "'" tempMaster.append(value) values = map((lambda x: x.strip()), tempMaster) printOut = insert + ' (' + ','.join(values) + ');') outFile.write(printOut + '\n') )。所以我问你的意见。如果这令人困惑或难以理解,我道歉。请让我知道我可以解决的问题,以便更容易理解是否是这种情况,并祝贺它到最后!

2 个答案:

答案 0 :(得分:2)

而不是

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

把这个

 values = map((lambda x: "'" + x.strip() + "'" if x!='NULL' else x), tempMaster)

修改

感谢接受/赞成我的简单技巧,但我不确定这是最佳的。 在更全局的范围内,你可以避免这种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

然后你value正确填充,节省内存和CPU。

答案 1 :(得分:0)

我检查了您的要求,我发现您的目录中有多个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)+")")

最后你有准备好的陈述,如下: -

qry = "INSERT into .. ("+",".join(staticColumnList)+") values " + ",".join(wholeDataList)