How to replace each element in a list with an element in the same position from another list? I thought something like this might work:
list1 = ['a', 'b', 'c', 'd']
list2 = ['a_replaced', 'b_replaced', 'c_replaced']
text = open(textfile, 'r')
n = 0
for line in text:
line = line[0:len(line)-1]
line.replace(col[n], outcol[n])
print line
n + 1
But it doesn't work. What am I doing wrong?
5 things:
You reference col and outcol which I assume are actually list1 and list2.
list1 and list2 are different sizes, this will crash
You're not checking the bounds on n, so if your text file is longer than 4 lines it will crash
The line n + 1 doesn't actually do anything, it should be n += 1
line.replace doesn't do an inline replace, it returns a new string.
So change it to line = line.replace(...).
I don't know what you're trying to accomplish. This program replaces a in line 1 with a_replaced, b in line 2 with b_replaced, c in line 3 with c_replaced, and d in line 4 with d_replaced.
replacements = [('a', 'a_replaced'), ('b', 'b_replaced'), ('c', 'c_replaced'), ('d', 'd_replaced')]
text = open(textfile, 'r')
n = 0
for line in text:
if n >= len(replacements):
break
print line[:-1].replace(replacements[n][0], replacements[n][1])
n += 1
However if your're trying to apply all replacements on each line, here's how:
replacements = [('a', 'a_replaced'), ('b', 'b_replaced'), ('c', 'c_replaced'), ('d', 'd_replaced')]
text = open(textfile, 'r')
for line in text:
line = line[:-1]
for oldtext, newtext in replacements:
line = line.replace(oldtext, newtext)
print line
Or a shorter version of the above program:
replacements = [('a', 'a_replaced'), ('b', 'b_replaced'), ('c', 'c_replaced'), ('d', 'd_replaced')]
text = open(textfile, 'r').read()
for oldtext, newtext in replacements:
text = text.replace(oldtext, newtext)
print text,
replace returns new string. You need line = line.replace(col[n], outcol[n]).
replace doesn't change the string, it returns a copy of the modified string.
line = line.replace(col[n], outcol[n])
I think this is what you are trying to achieve, although it is difficult to tell from the code that you have provided:
list1 = ['a', 'b', 'c', 'd']
list2 = ['a_replaced', 'b_replaced', 'c_replaced', 'd_replaced']
text = open(textfile, 'r')
for line in text:
for index, old in enumerate(list1):
line = line.replace(old, list2[index])
print line
text.close()
This should work. Comment to clarify
Related
I have two lists:
list1=('a','b','c')
list2=('2','1','3')
and a text file
the text file has 3 lines so I want to add
'a' in the 2nd line
'-' in others,
'b' in the 1st line
'-' in others, and
'c' in the 3rd line
'-' in others according to the list1 and list2 like this
xxxx-b-
xxxxa--
xxxx--c
First task is to get the first list sorted correctly. This is easy if you zip the two lists together and then sort based on the (int-converted) line number:
>>> list1 = ['a', 'b', 'c']
>>> list2 = ['2', '1', '3']
>>> sorted(zip(list1, list2), key=lambda p: int(p[1]))
[('b', '1'), ('a', '2'), ('c', '3')]
Then you need to format the letter into the appropriate string. I'd do that with something like:
'xxxx' + ''.join(char if char == letter else '-' for char in 'abc')
so all together it's:
>>> for row in [
... 'xxxx' + ''.join(char if char == letter else '-' for char in 'abc')
... for letter, _line in sorted(zip(list1, list2), key=lambda p: int(p[1]))
... ]:
... print(row)
...
xxxx-b-
xxxxa--
xxxx--c
Now you just need to write it to the appropriate text file instead of printing it; since you don't specify how you want to do that (is it a specific text file? is it the parameter to a function? is it an existing file you're appending to?) I'll leave that part for you to fill in. :)
I did it but I think there is a good method than my
list1=['1','4','3','2']
list2=['a','b','c','d']
j=0
while j < len(list1):
with open("note2.txt",'r+') as f:
line = f.readlines()
note=""
f.seek(0)
for index,line in enumerate(line):
if index==list1[j]:
note+=line.strip()+ str(list2[j])+'\n'
else:
note+=line.strip()+ '-\n'
f.write(note)
f.close()
j+=1
I have a text file (file.txt):
(A->[a:5,a:5,a:5,b:50,c:10,c:10])
(B->[e:120,g:50])
(C->[a:5,f:20])
and I want to extract and sum the values paired with 'a' (or 'b' or 'c' or ...) so that:
totalValue = 20 # of 'a'
#OR
totalValue = 50 # of 'b'
#OR
totalValue = 20 # of 'c'
Note: text file is obviously not a list, even though it looks like it.
myFile = open("file.txt", "r")
while True:
theline = myFile.readline()
if "a" in theline: #Just used 'a' here as an example.
for char in theline:
...
myFile.close()
That's roughly the code I have to read the file and check each line for 'a' (for example).
Thank you.
def find(s, ch):
return [i for i, ltr in enumerate(s) if ltr == ch]
myFile = open("file.txt", "r")
content = myFile.read()
totalValue = 0
all_colon_indexes = find(content,':')
for i in range(0,len(content)):
if content[i]==':':
if content[i-1]=='a': #THIS IS WHERE YOU SPECIFY 'a' or 'b' or 'c', etc
value=''
index = i+1
while True:
if content[index].isdigit()==True:
value=value+content[index]
index=index+1
else:
break
_value = int(value)
totalValue = totalValue + _value
print totalValue
result:
20
First, parse the couples using a regular expression which extracts them all.
Then use the nice itertools.groupby to gather the values using keys as the a,b,c... letter (first item of the regex tuple).
Finally, create tuples with variable, sum of values as integer
import re,itertools
with open("file.txt", "r") as myFile:
r = re.compile("(\w+):(-?\d+)")
for l in myFile:
tuples = r.findall(l)
sums = []
for variable,values in itertools.groupby(tuples,lambda t: t[0]):
sums.append((variable,sum(int(x[1]) for x in values)))
print(l,sums)
output:
(A->[a:5,a:5,a:5,b:50,c:10,c:10]) [('a', 15), ('b', 50), ('c', 20)]
(B->[e:120,g:50]) [('e', 120), ('g', 50)]
(C->[a:5,f:20]) [('a', 5), ('f', 20)]
If you want the total sum for all lines, small changes. First accumulate all tuples in a list (source line is not important), then apply groupby on the sorted list (or grouping won't work properly)
import re,itertools
with open("file.txt", "r") as myFile:
r = re.compile("(\w+):(-?\d+)")
tuples = []
for l in myFile:
tuples += r.findall(l)
sums = []
for variable,values in itertools.groupby(sorted(tuples),lambda t: t[0]):
sums.append((variable,sum(int(x[1]) for x in values)))
print(sums)
result:
[('a', 20), ('b', 50), ('c', 20), ('e', 120), ('f', 20), ('g', 50)]
No intention on stepping on Jean-Francois's toes :-) - I would suggest using Counter for count.
import collections
with open("file.txt", "r") as myFile:
r = re.compile("(\w+):(-?\d+)")
res = collections.Counter()
for l in myFile:
for key, cnt in r.findall(l):
res.update({key: int(cnt)})
result: res is now:
Counter({'e': 120, 'b': 50, 'g': 50, 'c': 20, 'f': 20, 'a': 20})
you can access it like a dictionary: ex:
res["a"] => 20
If I may suggest a somehow more compact solution that sums up every "key" in the text file and outputs a dictionary:
import re
from collections import defaultdict
with open('a.txt') as f:
lines = f.read()
tups = re.findall(r'(\w+):(\d+)', lines)
print(tups)
# tups is a list of tuples in the form (key, value), ie [('a': '5'), ...]
sums = defaultdict(int)
for tup in tups:
sums[tup[0]] += int(tup[1])
print(sums)
Will output:
[('a', '5'), ('a', '5'), ('a', '5'), ('b', '50'), ('c', '10'), ('c', '10'), ('e', '120'), ('g', '50'), ('a', '5'), ('f', '20')]
defaultdict(<class 'int'>, {'f': 20, 'b': 50, 'e': 120, 'a': 20, 'c': 20, 'g': 50})
And more specifically:
print(sums['a'])
>> 20
print(sums['b'])
>> 50
Parse the file using regular expressions:
\w stands for a word character
\d stands for a digit
+ specifies that you want to match one or more of the preceding match groups
? specifies that you want to match zero or one of the preceding match groups (to account for a minus character)
parentheses specify that what is matched inside them should be extracted as a group of characters so we have two groups (one for the letter, one for the number)
Then use a defaultdict to hold the name -> sum mapping. A defaultdict is like an ordinary dict, but when the key is missing, it creates it with a default value obtained by calling the callable you supplied when creating it. In this case this is int which returns 0 when called.
import re
from collections import defaultdict
value_pattern = re.compile("(\w+):(-?\d+)")
totals = defaultdict(int)
with open("file.txt", "r") as myFile:
for line in myFile.readlines():
values = value_pattern.findall(line)
for name, value in values:
totals[name] += int(value)
print(totals.items())
totals.clear()
This gives
dict_items([('c', 20), ('a', 15), ('b', 50)])
dict_items([('g', 50), ('e', 120)])
dict_items([('f', 20), ('a', 5)])
when run on your file.
I need to read a file containing information on different lines - for example the file may contain
12345678910
abcdefghij
zyxwvutsrq
I will then need to read the code diagonally so my list would be:
(1bx)(2cw)(3dv)
I have tried using zip and just can't figure out a way to get it to work.
EDIT
Is there anyway to also make it take into account the diagonals before the top left corner for example:
(ay)(z)
in the example file I used.
Edit 2: this is my almost complete code
with open(FileName) as diagonal :
a = diagonal.read().splitlines()
l = [a[i][i:] for i in range(len(a))]
Diaglist = [''.join(i) for i in zip(*l)]
with open(FileName) as diagonal1 :
b = diagonal1.read().splitlines()
o = [b[i][:i] for i in range(len(b))]
Diaglist1 = [''.join(i) for i in zip(*o)]
When I run the file I get the correct diagonals for the first with so from the top right to left but the second with so from the top right downwards I just get an empty list.
Do you mean:
>>> with open('file') as f:
... l = f.read().splitlines()
>>> l
['12345678910', 'abcdefghij', 'zyxwvutsrq']
>>> l = [l[0]] + [l[1][1:]] + [l[2][2:]] # remove 'a' from `l[1]` and `zy` from `l[2]`
>>> l
['12345678910', 'bcdefghij', 'xwvutsrq']
>>> list(zip(*l)) # zip them
[('1', 'b', 'x'), ('2', 'c', 'w'), ('3', 'd', 'v'), ('4', 'e', 'u'), ('5', 'f', 't'), ('6', 'g', 's'), ('7', 'h', 'r'), ('8', 'i', 'q')]
>>> [''.join(i) for i in list(zip(*l))] # also join them
['1bx', '2cw', '3dv', '4eu', '5ft', '6gs', '7hr', '8iq']
>>>
If you don't know how many lines in your file, we can use some magic code like [a[i][i:] for i in range(len(a))].
Try:
with open('file') as f:
a = f.read().splitlines()
l = [a[i][i:] for i in range(len(a))]
final_list = [''.join(i) for i in zip(*l)]
print(final_list)
As your edit, you can change a[i][i:] to a[i][:i]. Very simple:
with open('file') as f:
a = f.read().splitlines()
l = [a[i][:i] for i in range(len(a))]
final_list = [''.join(i) for i in zip(*l)][1:] # since the first element in the list will be empty (`''`), remove it.
print(final_list)
The following will work for an arbitrary number of lines of the same length, and wraps the final diagonals. This may not be what you want.
def diagonals(lines):
size = len(lines[0])
positions = [[(i + x) % size for x in range(len(lines))]
for i in range(size)]
return ["".join([lines[i][p] for i, p in enumerate(posn)])
for posn in positions]
>>> print(diagonals(['1234567891', 'abcdefghij', 'zyxwvutsrq']))
['1bx', '2cw', '3dv', '4eu', '5ft', '6gs', '7hr', '8iq', '9jz', '1ay']
I have a text file , which reads this.
a,b,c,d,e,f,g,h
a,b,c,i,j,k,l,m
f,k
Now, I want to store the first line as a list, second list in other list. But the third two values, I want to store in some particular variables say a=f, b=k.
I have made the code, but its showing error during reading the third line.
Please someone help this.
Here is my code.
filename = 'input.txt'
fin=open(filename,'r')
n=fin.readline()
m=fin.readline()
a,b=fin.readline()
UPDATE:
with open('input.txt') as fin:
n=fin.readline().split()
m=fin.readline().split()
line=(fin.readline())
a,b=line[0],line[2]
i=0
for i in range(0,len(n)):
if n[i]!=a:
i+=1
cp=i-1
i=0
for i in range(0,len(n)):
if n[i]!=a:
i+=1
posa=i-1
i=0
for i in range(0,len(n)):
if m[i]!=b:
i+=1
posb=i-1
while(posa>cp):
posa-=1
while(posa>cp):
posb-=1
if(cp<0):
print("No Common Predecessor")
elif (posa<posb):
if(posa<0):
posa=0
print("Common Predecessor: %s" %n[posa])
else:
if(posb<0):
posb=0
print("Common Predecessor: %s" %m[posb])
Method readline() returns string. To get a list you have to use:
m=fin.readline().strip().split(',')
n=fin.readline().strip().split(',')
a,b=fin.readline().strip().split(',')
Use with open;
with open('my.txt') as f:
lines = f.read().splitlines()
# lines[0] == 'a,b,c,d,e,f,g,h'
# lines[1] == 'a,b,c,i,j,k,l,m'
# lines[2] == 'f,k'
# lines[3] == '.'
n = list(lines[0].split(','))
m = list(lines[1].split(','))
a, b = lines[2].split(',')
# n == ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h ']
# m == ['a', 'b', 'c', 'i', 'j', 'k', 'l', 'm ']
# a == f
# b == k
Then you can do what you want with each line.
Your problem lies with the fact that a,b=fin.readline() would execute fin.readline() twice, giving you a = 'f,k' and b = '.' (which is the following line that is read)
To prevent this, you could assign the previous line to a variable and then split it into variables a and b.
For example:
filename = 'input.txt'
fin = open(filename )
n=fin.readline().split()
m=fin.readline().split()
line=(fin.readline())
a,b=line.split(',')
b=b.strip()
Or a more simplified approach using with open:
with open('input.txt') as fin:
n=fin.readline().split()
m=fin.readline().split()
line=(fin.readline())
a,b=line.split(',')
b=b.strip()
Both of these approches would yield the output:
>>> n
['a,b,c,d,e,f,g,h']
>>> m
['a,b,c,i,j,k,l,m']
>>> a
'f'
>>> b
'k'
I need to write a function, shuffleFiles(afile, bfile, cfile), that reads a line from file afile then reads a line from file bfile and appends these lines respectively to file C. If either file afile or bfile has been completely read then continue appending lines from the other file into file C.
This is the code I have so far, the lines are not being written to the file, but if i swap them out for print statements the lines print out in the correct order, just with blank \n in between most of them. not sure where to go from here
def shuffleFiles(afile, bfile, cfile):
fileA = open(afile, 'r')
fileB = open(bfile, 'r')
fileC = open(cfile, 'a')
fileADone = False
fileBDone = False
while not fileADone or not fileBDone:
if not fileADone:
line = fileA.readline()
line.rstrip()
line.strip()
if line == "" or line == " " or line == "/n":
fileADone = True
else:
fileC.write(str(line))
if not fileBDone:
line = fileB.readline()
line.rstrip()
line.strip()
if line == "" or line == " " or line == "/n":
fileBDOne = True
else:
fileC.write(str(line))
fileA.close()
fileB.close()
fileC.close()
Here's one way to iterate over two alternating iterables (files included):
from itertools import chain, izip_longest
fileA = open('file_A.txt')
fileB = open('file_B.txt')
for line in filter(None, chain.from_iterable(izip_longest(fileA, fileB))):
#Do stuff here.
The izip_longest "zips" together two or more iterables:
>>> a = [1, 2, 3, 4]
>>> b = ['a', 'b', 'c', 'd', 'e', 'f']
>>> list(izip_longest(a, b))
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (None, 'e'), (None, 'f')]
Then chain.from_iterable chains these into one long running iterable:
>>> list(chain.from_iterable(izip_longest(a, b)))
[1, 'a', 2, 'b', 3, 'c', 4, 'd', None, 'e', None, 'f']
Finally, filter with None as the first argument only returns the values with non-false values. In this case, it serves to filter out the Nones in the list above (Nones will occur when one iterable is longer than another), as well as to filter out '' empty strings that may be present in the files.
>>> filter(None, chain.from_iterable(izip_longest(a, b)))
[1, 'a', 2, 'b', 3, 'c', 4, 'd', 'e', 'f']
EDIT - Thanks to Tadeck
Putting all of this together, along with the more pythonic with operator for opening files, we get something like this:
with open('fileA.txt') as fileA, open('fileB.txt') as fileB, open('fileC.txt') as fileC:
lines = chain.from_iterable(izip_longest(fileA, fileB, fillvalue=''))
fileC.writelines(filter(None, (line.strip() for line in lines)))