如何遍历 2 个文件中的行,比较值并在满足条件时更新文件中的值?

     2023-03-12     103

关键词:

【中文标题】如何遍历 2 个文件中的行,比较值并在满足条件时更新文件中的值?【英文标题】:How to iterate over the rows from 2 files, compare the values and update the value in a file when the condition is met? 【发布时间】:2021-11-26 15:51:45 【问题描述】:

为了将值从 10 更改为 18、19 或 20,我正在拆分字符串,访问子字符串,然后尝试更改它。它的工作,但只是不改变价值观。这是我正在尝试实施的解决方案:

oldFileName = 'tryout.hmo'
newFileName = 'tryout_NEW.hmo'
topoFileName = 'Density.topo'

readme = open( oldFileName, "r" )
oldLines = readme.readlines()       

readme = open(topoFileName, "r")
Lines = readme.readlines()
readme.close()

newFile = open(newFileName,"w")


for row in oldLines:
    for line in Lines:
        tmp = line.split()
    list =  row.rstrip()
    tmp1 = list.split()
    newFile.write(row)
    if row.find("BEG_ELEM_DATA") > -1:
       if tmp[0] == tmp1[0]:
           if tmp[2] == 1 and tmp[3] == 0:
            # it is magnet, value 18
             newFile.write(tmp1.replace(tmp1[1], "18"))
         
           elif tmp[2] == 1 and tmp[3] == 1:               
              # it is iron, value 19
             newFile.write(tmp1.replace(tmp1[1], "19"))
         
           else:
            # it is air, value 20
             newFile.write(tmp1.replace(tmp1[1], "20")) 

newFile.close()      

如果你能在上面的脚本中解决这个问题,我将不胜感激,那么我想它应该可以工作。

【问题讨论】:

【参考方案1】:

最后,这是您正在寻找的解决方案。

import pandas as pd
df2 = pd.read_csv('Density.topo', header = 0, names = list('ABCD'), delimiter=r'\s+', skiprows=1)
df2[['C', 'D']]= df2[['C', 'D']].round()

new_file_content=''

with open('tryout.hmo', 'r') as f:
    for line in f:

        if line[11:13] == '10':

            if line[3].isspace():
                ID_to_search_for = line[4:8] # number with 4 digits
            else:
                ID_to_search_for = line[3:8] # number with 5 digits
            search_idx = df2[df2['A'] == ID_to_search_for].index[0]

            if df2['C'][search_idx] == 1 and df2['D'][search_idx] == 0:
                change = '18' #magnet
                new_line = line[:11] + change + line[13:]
            elif df2['C'][search_idx] == 1 and df2['D'][search_idx] == 1:
                change = '19' #iron
                new_line = line[:11] + change + line[13:]
            else:
                change = '20' #air
                new_line = line[:11] + change + line[13:]

            new_file_content += new_line

        else:
            new_file_content += line
    
with open('tryout_changed.hmo', 'w') as f:
    f.write(new_file_content)

如果你不想使用数据框,你可以这样做:

with open('density.topo') as f:
    lists_of_list = [line.rstrip().split() for line in f]

new_file_content=''
with open('tryout_test.hmo', 'r') as f:
    
    for line in f:
        
        if line[11:13] == '10':
            if line[3].isspace():
                ID_to_search_for = line[4:8] # number with 4 digits
            else:
                ID_to_search_for = line[3:8] # number with 5 digits
            for idx, sublist in enumerate(lists_of_list):
                if sublist[0] == ID_to_search_for:                    
                    if lists_of_list[idx][2] == 1 and lists_of_list[idx][3] == 0:
                        change = '18' #magnet
                        new_line = line[:11] + change + line[13:]
                    elif lists_of_list[idx][2] == 1 and lists_of_list[idx][3] == 1:
                        change = '19' #iron
                        new_line = line[:11] + change + line[13:]
                    else:
                        change = '20' #air
                        new_line = line[:11] + change + line[13:]

                    new_file_content += new_line

        else:
            new_file_content += line
    
with open('tryout_changed.hmo', 'w') as f:
    f.write(new_file_content)

好的,这是我的最终答案。它(再次)执行您正在搜索的所有内容。如果有问题,请在您的 IDE 中调试您的代码。您应该开始使用上下文管理器,而不是逐步打开和关闭文件。 我在问题中围绕您的代码编写了新代码,并向其中添加了一些 cmets。

oldFileName = 'tryout.hmo'
newFileName = 'tryout_NEW.hmo'
topoFileName = 'Density.topo'

readme = open( oldFileName, "r" )
oldLines = readme.readlines()

m = int(oldLines[3])
print(m)
new_m = m+3
m1 = str(m)
new_m1 = str(new_m)

Phrase = "END_COMP_DATA"
#n = "Phrase not found" #not used --> not needed

with open(oldFileName,"r") as oldFile: 
    for number, lin in enumerate(oldFile):
        if Phrase in lin:
          n = number
       
#insert 3 lines to tryout_new at the right position (--> row n)
magnet = f"      m+1 "'"                     topo_magnet"'"\n" 
iron   = f"      m+2 "'"                       topo_iron"'"\n" 
air    = f"      m+3 "'"                        topo_air"'"\n"  
    
oldLines[n:n] = [magnet, iron, air]

newFile = open(newFileName,"w") 
flag = 0

with open('density.topo') as f:
    data_density = [line.rstrip().split() for line in f]

for idx, row in enumerate(oldLines):
    lst =  row.rstrip() #I think you shouldn't name a variable like a class in python (list). use 'lst' or something like that
    tmp_tryout = lst.split()
    if row.find("BEG_ELEM_DATA") > -1:
        flag = 1
    if flag == 1 and len(tmp_tryout)>1:
        # if the column has more than 2 columns (after split), check for the "10"
        if tmp_tryout[1] == '10':
            # density_idx_line searchs in density.topo for a match with tmp_tryout[0] (e.g. 3749) and stores the whole line
            density_idx_line = list(filter(lambda x: x[0] == tmp_tryout[0], data_density))
            if len(density_idx_line) >0:
                if density_idx_line[0][2] == '1.0' and density_idx_line[0][3] == '1e-05':
                    # the ' 10 ' is the 10 with a whitespace before and after it. Only like this only the 10 gets replaced (and not e.g. 3104 to 3184)    
                    newFile.write(row.replace(' 10 ', ' 18 '))       
                elif density_idx_line[0][2] == '1.0' and density_idx_line[0][3] == '1.0':               

                    newFile.write(row.replace(' 10 ', ' 19 ')) 
                else:

                    newFile.write(row.replace(' 10 ', ' 20 '))
        else: 
            newFile.write(row)
    else: 
        if idx == 3: 
            newFile.write(row.replace(m1, new_m1)) 
        else:
            newFile.write(row)       
                
newFile.close()
print ("script terminated successfully!")

【讨论】:

此代码将有效,但仅适用于此特定文件而不适用于其他文件,很可能我在 python 中搜索解决方案而不使用数据框。我在 python 中尝试了一种解决方案,它几乎可以工作但没有更新值,我会在那里标记你。 其他文件是什么意思?这个文件的格式很乱,所以我只是为这个特殊的文件编写了代码。如果您想更一般地使用它,您可以使用正则表达式来查找所有这些空格之间的不同“列”,这些空格一直在变化。不使用数据框也不应该是一个大问题,只是比较第二个文件中的值的不同方式(因为对我来说更困难的问题是在试用文件中查找和更改值)。是的,如果您让我知道您的最终解决方案是什么样的,我将不胜感激。 是的,我在更改试用文件中的值时也面临同样的问题。我将编辑我的问题并将代码放在我上面的问题中。如果你能找到这方面的灵魂,我将不胜感激,然后它可以用于所有其他文本文件。 我已经在没有问题的答案解决方案部分添加了代码。请在上面检查。此外,在不使用数据框的代码中,仅将值从 10 更改为 20。 我会尽力的。我将在答案中查看并调试您的脚本。您使用什么 IDE,或者您在哪里编写代码?你为什么不使用我的建议?如果处处为 20,则 if/elif 条件永远不会正确。你也可以在你的地方调试我的代码为什么它不工作......对我来说它工作。【参考方案2】:

好的,这是另一个解决方案。对于阅读本文的其他人:这仍然只是一个临时解决方案,但@Sagar 和我都不知道如何做得更好。

import pandas as pd
df = pd.read_csv('tryout.hmo', header = 0, names = list('ABCDEFGHIJKLM'), delimiter=r'\s+', skiprows=[i for i in range(52362)])
df2 = pd.read_csv('Density.topo', header = 0, names = list('ANOP'), delimiter=r'\s+', skiprows=1)
df2 = df2.iloc[:-3, :]

df3 = df.merge(df2, how='outer', on='A')
df3[['O','P']] = df3[['O','P']].fillna(-1).astype(int).replace(-1, np.nan)

df3['B']= df3.apply(lambda x: 18 if x['B']==10 and x['O']==1 and x['P']==0 else (
    19 if x['B']==10 and x['O']==1 and x['P']==1 else (
    20 if x['B']==10 and x['O']==0 and x['P']==0 else x['B'])), axis=1)

df3.to_csv('new_tryout.csv')

它在不到一秒的时间内完成了代码,因此它比 iterrows 或 itertuples 好得多。 新的 csv 文件包括试用文件和密度文件。它们由试用文件的第一列合并在一起(我猜是 ID)

我没有检查所有这些非常大的文件,但从我检查的几个随机点来看,似乎这种方式有效。

【讨论】:

我检查了它,但是如果您检查了诸如 3749 之类的元素或任何在试用文件中具有值 10 的元素没有更改,则该文件也没有正确合并。它很难使用合并文件,因为我希望它在具有更改值的同一个试用文件中。 是的,试用文件根本没有改变。它是关于 new_tryout 文件的,我刚刚检查了 3749。它的值应该是 18。在将其保存为 new_tryout 文件之前,您可以删除最后 3 列,这样您就只有原始的试用列,没什么大不了的 是的,我的意思是在new_tryout文件中,3749行如下:2765,3749,10.0,106.0,10690.0,10692.0,10693.0,10695.0,10658.0,10689.0,,,,,2, 1.0,0.0.,所以 10 的值在我的 csv 中没有改变。此外,正如您所说,new_tryout 文件需要删除最后三列和第一列,并添加试用文件的其余部分,然后它将是更改值的试用文件。我猜这变得更复杂了,你怎么看? 很奇怪。您是否完全按照我发布的方式复制粘贴了我的代码?也许你有不同的python版本。对于您问题的第二部分:删除列很容易。由于列不一致,添加试用文件的第一部分可能有点棘手。我会尽力。不过,这对我来说总是很好的做法。 我使用的是 3.9.5 python 版本。【参考方案3】:

我还是 Python 的初学者,但我试图解决您的问题,这是我的解决方案:

我想有更好的方法可以做到这一点,因为您必须在比较之前将所有数据导入数据框。

另外我不知道您是否可以使用 pd.read_csv 将数据读取到数据框,因为我不知道 *.hmo 和 *.topo

import pandas as pd

df = pd.read_csv('tryout.csv', delimiter=';')
df2 = pd.read_csv('density.csv', delimiter=';')

for idx, row in df.iterrows():
    for idx2, row2 in df2.iterrows():
        if row[0] == row2[0]:
            if row2[2] == 1 and row2[3] == 0 :
                # it is magnet, value 18
                row[1] = 18
            elif row2[2] == 1 and row2[3] == 1 :
                # it is iron, value 19
                row[1] = 19
            else:
                # it is air, value 20
                row[1] = 20
df.to_csv('new_tryout.csv')

我的代码在这里做什么,它将两个文件都加载到数据帧中。然后遍历每一行以比较两个文件中的 ID 相同的位置(例如 3749)。 如果为真,则有 3 个 if 语句是否是磁铁/铁/空气,并将 df 中的值更改为正确的数字。

最后将新的df保存到一个新文件'new_tryout.csv'

我为它创建了 2 个测试文件,它按应有的方式工作。

【讨论】:

感谢您的回复。它在数据框中很容易,但主要问题是试用文件很难转换为 csv,因为它具有不同大小的行和列,这在我上面解释的整个试用文件中有所不同,我不确定元素列是行 [0]这是第一列(如果它在数据框中,但我猜不是在这里)这就是为什么我尝试使用 python 并且仅在试用文件中的 BEG_ELEM_DATA 中需要从 10 更改为 18 或 19 或 20。如果你愿意,我可以分享我的文件,但这里没有分享选项,是吗? 您知道 BEG_ELEM_DATA 是否具有相同的列大小吗?然后您可以跳过 BEG_ELEM_DATA 开始之前的所有行,然后按照建议将其读入 我尝试了使用 pd.read_csv(r'path\file name.txt) 和 to_csv 方法进行转换的常用方法,但问题是这些值不在单独的列中:对于密度文件- 一列中的所有值,如 3749 10 1.0 0.0 和试用文件中的所有值。你知道如何解决这个问题吗? 不知道有没有直接分享数据的方法。您可以将其上传到某处并在此处复制链接。 如果我理解正确,您只需将分隔符设置为制表符 (delimiter='\t')

比较 2 个表中的值并生成具有差异的新表

】比较2个表中的值并生成具有差异的新表【英文标题】:Comparevaluesfrom2tablesandproduceanewtablewiththedifferences【发布时间】:2017-09-0720:56:51【问题描述】:我正在尝试在SQLServer(脚本)中找到一种方法:给定2个表,具有相同的列结构... 查看详情

如何使用 shell 遍历外部文件中的行? [复制]

】如何使用shell遍历外部文件中的行?[复制]【英文标题】:HowdoIiteratethroughlinesinanexternalfilewithshell?[duplicate]【发布时间】:2012-07-0604:22:06【问题描述】:我有一个包含名称列表的文件。我需要使用shell脚本从外部文件中遍历此文... 查看详情

是否可以就地修改文件中的行?

...1-03-2723:39:58【问题描述】:是否可以逐行解析文件,并在遍历这些行时就地编辑一行?【问题讨论】:在某些条件下是可能的。如果编辑处理的行所产生的行较短或与处理的行相同,则很容易做到。如果不是这种情况,它会变得... 查看详情

返回值并在 UDF 中分配单元格

...要在使用多个vlookup函数返回值之前将单元格连接到两个文件中的一个单元格中。然后我尝试构建一个UDF,它允许定义搜索键(来自第一个工作表)和搜索键(来自第二个 查看详情

如何使不满足特定条件的行不出现在结果中

】如何使不满足特定条件的行不出现在结果中【英文标题】:Howtomakerowsthatdon\'tsatisfyacertainconditionnotappearinaresult【发布时间】:2015-08-1708:29:19【问题描述】:我有一个表T1,其中包含以下列和行/行数据:表T1child_id|孩子一个|儿童... 查看详情

如何遍历 macOS 应用程序窗口直到满足条件?

】如何遍历macOS应用程序窗口直到满足条件?【英文标题】:HowtoiterateoveramacOSapp’swindowsuntilaconditionismet?【发布时间】:2018-03-3117:18:54【问题描述】:要遍历我的macOS应用程序中的所有窗口,我使用enumerateWindows(options:using:),如下... 查看详情

如何在 Jquery 中获取文件值并在 AJAX 中传递值 [重复]

】如何在Jquery中获取文件值并在AJAX中传递值[重复]【英文标题】:HowtogetthefilevalueinJqueryandpassvalueinAJAX[duplicate]【发布时间】:2017-02-0813:31:06【问题描述】:在这里我想在这里插入数据库中的值正常值,如姓名,电子邮件,区域...... 查看详情

创建数组后,如何正确遍历 CSV 文件中的行数组?

】创建数组后,如何正确遍历CSV文件中的行数组?【英文标题】:HowtoproperlyiteratethroughanarrayofrowsfromaCSVfile,afterthearrayhasbeencreated?【发布时间】:2018-03-3012:48:35【问题描述】:非常抱歉,如果之前回答过这个问题,但我搜索了***并... 查看详情

如何在 C++ 程序中的 2 个特定字符之间比较 2 个文件中的文本行

】如何在C++程序中的2个特定字符之间比较2个文件中的文本行【英文标题】:HowdoIcomparetextlinesin2filesbetween2specificcharactersinaC++program【发布时间】:2020-12-1723:30:32【问题描述】:我正在编写这个程序,它清理xml文件并将新行从txt文... 查看详情

将行与标题进行比较,然后在列中插入值并在 VBA 中进行重复检查

...我..第1步:将行与每个SU标头进行比较。在第2行中,SU_BS中的值为211。一旦SU中有值,NAM 查看详情

如何返回满足特定条件的行列表以及它之前的行?

】如何返回满足特定条件的行列表以及它之前的行?【英文标题】:HowcanIreturnthelistofrowsmeetingacertainconditionwiththerowjustbeforeit?【发布时间】:2020-12-2416:06:24【问题描述】:precise_value_datelocal_limit_amount2020-12-1018:45:37.6501800000.0000002020-... 查看详情

如何比较 2 个 iframe 并在视觉上获得差异?

】如何比较2个iframe并在视觉上获得差异?【英文标题】:Howtocompare2iframesandgetdifferencevisually?【发布时间】:2020-05-2205:50:11【问题描述】:案例:我有2个iframe,并且都有很多div和其他控件,所以这两个iframe都像HTML网站的中等大小... 查看详情

只读大文本文件中满足特定条件的行

】只读大文本文件中满足特定条件的行【英文标题】:Readonlylinesfromalargetextfilewhichfulfillspecificcondition【发布时间】:2017-03-1105:42:22【问题描述】:我有一个包含3列的大文件(data.txt,35GB)。该文件的一些示例部分如下所示:........ 查看详情

如果条件为真,如何循环 LibreOffice Calc 电子表格中的行范围、比较单元格值、设置单元格值和删除行

】如果条件为真,如何循环LibreOfficeCalc电子表格中的行范围、比较单元格值、设置单元格值和删除行【英文标题】:HowtolooponrangeofrowsinLibreOfficeCalcspreadsheet,comparingcellvalues,settingcellvaluesanddeletingrow,ifconditionistrue【发布时间】:2020-0... 查看详情

MYSQL SELECT:如何获取一个额外的列,指示是不是满足 WHERE 子句中的第一个或第二个条件?

】MYSQLSELECT:如何获取一个额外的列,指示是不是满足WHERE子句中的第一个或第二个条件?【英文标题】:MYSQLSELECT:HowtogetanadditionalcolumnthatindicateswhetherthefirstorthesecondconditioninaWHEREclausewasmet?MYSQLSELECT:如何获取一个额外的列,指示... 查看详情

如果在 R 中满足条件,则从前一行获取值并连接

...并与当前行字符串连接条件:如果\'Flag\'为1,则在从AG列中的前一行获取字符串并从AG列中获取当前行字符串之后进行连接。我的数据框示例在此下方给出,所需 查看详情

如何遍历 Hashmap、打印键/值并删除 Rust 中的值?

】如何遍历Hashmap、打印键/值并删除Rust中的值?【英文标题】:HowtoiteratethroughaHashmap,printthekey/valueandremovethevalueinRust?【发布时间】:2018-01-2505:50:45【问题描述】:这在任何语言中都应该是一项微不足道的任务。这在Rust中不起作... 查看详情

如何比较ag-grid中的行

】如何比较ag-grid中的行【英文标题】:Howtocomparerowsinag-grid【发布时间】:2019-10-2603:29:19【问题描述】:我正在尝试比较我的ag-grid中的两个相似行并突出显示它们之间的差异。大多数列条目是相同的,但如果单元格与其前身不同... 查看详情