Python: Find specific sum of values? - python

I am trying to find the sum of to values from a text file that is equal to 2020 with python. The text file contains multiple numbers each written in one line like this:
What is the easiest and fastest way to do this in python?
My code reads in the file correctly but does not access the inner for loop?
data = []
try:
file = open('/Users/korbinianschleifer/desktop/input.txt', 'r+')
data = file.readlines()
file.close()
except x:
print('file could not be loaded')
print(len(data))
for i in range(len(data)):
for j in range(i+1,len(data)):
if data[i]+data[j] == 2020:
print('solution found')

Your data list is a list of strings, which means + will concatenate them ("1" + "1" is "11"), which is not the behavior you want. Parse your data to an int:
# use with to avoid having to close the file manually
with open('/Users/korbinianschleifer/desktop/input.txt', 'r+') as file:
data = file.readlines()
# parse it to an int
data = [int(x) for x in data]
for i in range(len(data)):
for j in range(i + 1, len(data)):
if data[i] + data[j] == 2020:
print("solution found", data[i], data[j])
As a side note, the faster way to do this is to maintain a set of values:
# use with to avoid having to close the file manually
with open('/Users/korbinianschleifer/desktop/input.txt', 'r+') as file:
data = file.readlines()
# parse it to an int
data = [int(x) for x in data]
seen = set()
for v in data:
if 2020 - v in seen:
print("solution found", v, 2020 - v)
seen.add(v)

Related

How to transform a csv file into a multi-dimensional list using Python?

I started out with a 4d list, something like
tokens = [[[["a"], ["b"], ["c"]], [["d"]]], [[["e"], ["f"], ["g"]],[["h"], ["i"], ["j"], ["k"], ["l"]]]]
So I converted this to a csv file using the code
import csv
def export_to_csv(tokens):
csv_list = [["A", "B", "C", word]]
for h_index, h in enumerate(tokens):
for i_index, i in enumerate(h):
for j_index, j in enumerate(i):
csv_list.append([h_index, i_index, j_index, j])
with open('TEST.csv', 'w') as f:
# using csv.writer method from CSV package
write = csv.writer(f)
write.writerows(csv_list)
But now I want to do the reverse process, want to convert a csv file obtained in this format, back to the list format mentioned above.
Assuming you wanted your csv file to look something like this (there were a couple typos in the posted code):
A,B,C,word
0,0,0,a
0,0,1,b
0,0,2,c
...
here's one solution:
import csv
def import_from_csv(filename):
retval = []
with open(filename) as fh:
reader = csv.reader(fh)
# discard header row
next(reader)
# process data rows
for (x,y,z,word) in reader:
x = int(x)
y = int(y)
z = int(z)
retval.extend([[[]]] * (x + 1 - len(retval)))
retval[x].extend([[]] * (y + 1 - len(retval[x])))
retval[x][y].extend([0] * (z + 1 - len(retval[x][y])))
retval[x][y][z] = [word]
return retval
def import_from_csv(file):
import ast
import csv
data = []
# Read the CSV file
with open(file) as fp:
reader = csv.reader(fp)
# Skip the first line, which contains the headers
next(reader)
for line in reader:
# Read the first 3 elements of the line
a, b, c = [int(i) for i in line[:3]]
# When we read it back, everything comes in as strings. Use
# `literal_eval` to convert it to a Python list
value = ast.literal_eval(line[3])
# Extend the list to accomodate the new element
data.append([[[]]]) if len(data) < a + 1 else None
data[a].append([[]]) if len(data[a]) < b + 1 else None
data[a][b].append([]) if len(data[a][b]) < c + 1 else None
data[a][b][c] = value
return data
# Test
assert import_from_csv("TEST.csv") == tokens
First, I'd make writing this construction in a CSV format independent from dimensions:
import csv
def deep_iter(seq):
for i, val in enumerate(seq):
if type(val) is list:
for others in deep_iter(val):
yield i, *others
else:
yield i, val
with open('TEST.csv', 'w') as f:
csv.writer(f).writerows(deep_iter(tokens))
Next, we can use the lexicographic order of the indices to recreate the structure. All we have to do is sequentially move deeper into the output list according to the indices of a word. We stop at the penultimate index to get the last list, because the last index is pointing only at the place of the word in this list and doesn't matter due to the natural ordering:
with open('TEST.csv', 'r') as f:
rows = [*csv.reader(f)]
res = []
for r in rows:
index = r[:-2] # skip the last index and word
e = res
while index:
i = int(index.pop(0)) # get next part of a current index
if i < len(e):
e = e[i]
else:
e.append([]) # add new record at this level
e = e[-1]
e.append(r[-1]) # append the word to the corresponding list

Python: write function return value to output file

I have 5 input files. I'm reading the targets & arrays from the 2nd & 3rd lines. I have 2sum function. I need to output the function's returned value(s) and output them to 5 output files.
I know my functions correct. I print it out just fine.
I know I'm reading 5 input files & creating & writing to 5 output files.
What I can't figure out is how to write my return value(s) from the twoSum function INTO the output function.
def twoSum(arr, target):
for i in range(len(arr)):
for j in range(i, len(arr)):
curr = arr[i] + arr[j]
if arr[i]*2 == target:
return [i, i]
return answer
if curr == target:
return [i, j]
Read 5 files
inPrefix = "in"
outPrefix = "out"
for i in range(1, 6):
inFile = inPrefix + str(i) + ".txt"
with open(inFile, 'r') as f:
fileLines = f.readlines()
target = fileLines[1]
arr = fileLines[2]
how do i get write twoSum's value to output file?
???????
Output to 5 files
outFile = outPrefix + str(i) + ".txt"
with open(outFile, 'a') as f:
f.write(target) #just a test to make sure I'm writing successfully
f.write(arr) #just a test to make sure I'm writing successfully
Two things that come to mind:
open the file in wt mode (Write Text).
processedOutput appears to be a list. When you write to a file, you need write a string. Are you wanting a CSV style output of those values ? or just a line of spaced out values ? The simplest way here, would be something like: " ".join(processedOutput). That will separate all the items in your processedOut list by a string.

CSV Python Outputting: Outputting non-matching field once rather than once for every item in list

I've been trying to figure this out for about a year now and I'm really burnt out on it so please excuse me if this explanation is a bit rough.
I cannot include job data, but it would be accurate to imagine 2 csv files both with the first column populated with values (Serial numbers/phone numbers/names, doesn't matter - just values). Between both csv files, some values would match while other values would only be contained in one or the other (Timmy is in both files and is a match, Robert is only in file 1 and does not match any name in file 2).
I can successfully output a csv value ONCE that exists in the both csv files (I.e. both files contain "Value78", output file will contain "Value78" only once).
When I try to tack on an else statement to my if condition, to handle non-matching items, the program will output 1 entry for every item it does not match with (makes 100% sense, matches happen once but every other comparison result besides the match is a non-match).
I cannot envision a structure or method to hold the fields that don't match back so that they can be output once and not overrun my terminal or output file.
My goal is to output two csv files, matches and non-matches, with the non-matches having only one entry per value.
Anyways, onto the code:
import csv
MYUNITS = 'MyUnits.csv'
VENDORUNITS = 'VendorUnits.csv'
MATCHES = 'Matches.csv'
NONMATCHES = 'NonMatches.csv'
with open(MYUNITS,mode='r') as MFile,
open(VENDORUNITS,mode='r') as VFile,
open(MATCHES,mode='w') as OFile,
open(NONMATCHES,mode'w') as NFile:
MyReader = csv.reader(MFile,delimiter=',',quotechar='"')
MyList = list(MyReader)
VendorReader = csv.reader(VFile,delimiter=',',quotechar='"')
VList = list(VendorReader)
for x in range(len(MyList)):
for y in range(len(VList)):
if str(MyList[x][0]) == str(VList[y][0]):
OFile.write(MyList[x][0] + '\n')
else:
pass
The "else: pass" is where the logic of filtering out non-matches is escaping me. Outputting from this else statement will write the non-matching value (len(VList) - 1) times for an iteration that DOES produce 1 match, the entire len(VList) for an iteration with no match. I've tried using a counter and only outputting if the counter equals the len(VList), (incrementing in the else statement, writing output under the scope of the second for loop), but received the same output as if I tried outputting non-matches.
Below is one way you might go about deduplicating and then writing to a file:
import csv
MYUNITS = 'MyUnits.csv'
VENDORUNITS = 'VendorUnits.csv'
MATCHES = 'Matches.csv'
NONMATCHES = 'NonMatches.csv'
list_of_non_matches = []
with open(MYUNITS,mode='r') as MFile,
open(VENDORUNITS,mode='r') as VFile,
open(MATCHES,mode='w') as OFile,
open(NONMATCHES,mode'w') as NFile:
MyReader = csv.reader(MFile,delimiter=',',quotechar='"')
MyList = list(MyReader)
VendorReader = csv.reader(VFile,delimiter=',',quotechar='"')
VList = list(VendorReader)
for x in range(len(MyList)):
for y in range(len(VList)):
if str(MyList[x][0]) == str(VList[y][0]):
OFile.write(MyList[x][0] + '\n')
else:
list_of_non_matches.append(MyList[x][0])
# Remove duplicates from the non matches
new_list = []
[new_list.append(x) for x in list_of_non_matches if x not in new_list]
# Write the new list to a file
for i in new_list:
NFile.write(i + '\n')
Does this work?
import csv
MYUNITS = 'MyUnits.csv'
VENDORUNITS = 'VendorUnits.csv'
MATCHES = 'Matches.csv'
NONMATCHES = 'NonMatches.csv'
with open(MYUNITS,'r') as MFile,
(VENDORUNITS,'r') as VFile,
(MATCHES,'w') as OFile,
(NONMATCHES,mode,'w') as NFile:
MyReader = csv.reader(MFile,delimiter=',',quotechar='"')
MyList = list(MyReader)
MyVals = [x for x in MyList]
MyVals = [x[0] for x in MyVals]
VendorReader = csv.reader(VFile,delimiter=',',quotechar='"')
VList = list(VendorReader)
vVals = [x for x in VList]
vVals = [x[0] for x in vVals]
for val in MyVals:
if val in vVals:
OFile.write(Val + '\n')
else:
NFile.write(Val + '\n')
#for x in range(len(MyList)):
# for y in range(len(VList)):
# if str(MyList[x][0]) == str(VList[y][0]):
# OFile.write(MyList[x][0] + '\n')
# else:
# pass
Sorry, I had some issues with my PC. I was able to solve my own question the night I posted. The solution I used is so simple I'm kicking myself for not figuring it out way sooner:
import csv
MYUNITS = 'MyUnits.csv'
VENDORUNITS = 'VendorUnits.csv'
MATCHES = 'Matches.csv'
NONMATCHES = 'NonMatches.csv'
with open(MYUNITS,mode='r') as MFile,
open(VENDORUNITS,mode='r') as VFile,
open(MATCHES,mode='w') as OFile,
open(NONMATCHES,mode'w') as NFile:
MyReader = csv.reader(MFile,delimiter=',',quotechar='"')
MyList = list(MyReader)
VendorReader = csv.reader(VFile,delimiter=',',quotechar='"')
VList = list(VendorReader)
for x in range(len(MyList)):
tmpStr = ''
for y in range(len(VList)):
if str(MyList[x][0]) == str(VList[y][0]):
tmpStr = '' #Sets to blank so comparison fails, works because break
OFile.write(MyList[x][0] + '\n')
break
else:
tmp = str(MyList[x][0])
if tmp != '':
NFile.write(tmp + '\n')

How to write a unique value to a csv with python

I am trying to writer unique values to a csv that already has a list of ints inside it.
Currently I have tried to loop through a range of possible numbers then check if those numbers are in the csv. It appears that the checking is not working properly.
def generateUserCode():
with open ('/MyLocation/user_codes.csv') as csvDataFile:
userCodes = csv.reader(csvDataFile)
for x in range(0, 201):
if x not in userCodes:
return x
def writeUserCode(userCode):
with open ('/MyLocation/user_codes.csv', 'a') as csvDataFile:
csvDataFile.write('\n' + str(userCode))
userCode = generateUserCode()
writeUserCode(userCode)
So it should print the first number not in the csv and add the number to the csv. However all it is doing is printing 0 and adding 0 to my csv every time it is run even if 0 is in the csv.
Update:
The csv looks something like this:
3
4
5
35
56
100
There are more values but it is generally the same with no repeats and values between 0 and 200
The problem is with the following line:
if x not in userCodes:
userCodes is not a list it is a csvReader object. Also, you should use
if str(x) not in line:
#use str(x) instead of x
This is the code that works for me:
import csv
def generateUserCode():
with open ('file.csv') as csvDataFile:
csvread = csv.reader(csvDataFile)
userCodes = []
#print(userCodes)
for line in csvread:
try:
userCodes.append(line[0]) # As long as the code is the first
# element in that line, it should work
except:
IndexError # Avoid blank lines
print(userCodes)
for x in range(0, 201):
if str(x) not in userCodes:
return x
def writeUserCode(userCode):
with open ('file.csv', 'a') as csvDataFile:
csvDataFile.write('\n' + str(userCode))
userCode = generateUserCode()
writeUserCode(userCode)
Iterating userCodes shows each item is a list of strings:
for x in userCodes:
print(x)
returns:
['3']
['4']
['5']
['35']
['56']
['100']
So there are a lot of possible fixes, one would be:
def generateUserCode():
with open ('/MyLocation/user_codes.csv') as csvDataFile:
userCodes = csv.reader(csvDataFile)
userCodes = [int(item[0]) for item in userCodes]
for x in range(0, 201):
if x not in userCodes:
return x
It’s tricky to answer without seeing the CSV, but when you read the CSV, all fields are strings. Therefor you need to convert either the userCodes to int or x to string for the comparison to work.
For example:
userCodes = [int(d[0]) for d in csv.reader(csvDataFile)]
for x in range(0, 201):
if x not in userCodes:
return x
You are checking if a str is in an instance of csv.reader. This syntax doesn't work even with a normal file handle:
with open('somefile.txt') as fh:
x = fh.read()
x
'Spatial Reference: 43006\nName: Jones Tract\n424564.620666, 4396443.55267\n425988.30892, 4395630.01652\n426169.09473, 4395426.63249\n426214.291182, 4395268.4449\n\nName: Lewis Tract\n427909.158152, 4393935.14955\n428587.104939, 4393731.76552\n428700.096071, 4393528.38148\n428745.292523, 4393347.59567\n\nName: Adams Tract\n424180.450819, 4393957.74778\n424361.236629, 4393709.16729\n424655.013571, 4393641.37261\n424858.397607, 4393776.96197\n'
# now check if 'e' is in fh
with open('somefile.txt') as fh:
'e' in fh
False
'e' in x
True
Also, your csv file isn't really a csv file, so I'd just use a normal file handle and ignore the csv entirely.
The better approach may be to aggregate your codes in a set and check from there:
def get_codes():
with open('user_codes.csv') as fh:
# return a set to test membership quickly
return {line.strip() for line in fh}
codes = get_codes()
def add_code(code):
if code not in codes:
codes.add(code)
with open('user_codes.csv', 'a') as fh:
fh.write(code)
else:
raise ValueError("Code already exists")
# or do something else
add_code(88)
add_code(88)
# ValueError
To generate a user code automatically, since you are using a range, this becomes relatively easy:
def generate_user_code():
try:
# this returns the first number not in codes
return next(i for i in range(201) if i not in codes)
except StopIteration:
# you've exhausted your range, nothing is left
raise ValueError("No unique codes available")
# and your write method can be changed to
def add_code(code):
with open('user_codes.csv', 'a') as fh:
codes.add(code)
fh.write(code)
codes = get_codes()
user_code = generate_user_code()
add_code(user_code)
You may try to do this:
....
userCodes = csv.reader(csvDataFile)
uc = []
for y in userCodes:
uc += y
for x in range(0, 201):
if str(x) not in uc:
return x
....

How to rearrange numbers from different lines of a text file in python?

So I have a text file consisting of one column, each column consist two numbers
190..255
337..2799
2801..3733
3734..5020
5234..5530
5683..6459
8238..9191
9306..9893
I would like to discard the very 1st and the very last number, in this case, 190 and 9893.
and basically moves the rest of the numbers one spot forward. like this
My desired output
255..337
2799..2801
3733..3734
5020..5234
5530..5683
6459..8238
9191..9306
I hope that makes sense I'm not sure how to approach this
lines = """190..255
337..2799
2801..3733"""
values = [int(v) for line in lines.split() for v in line.split('..')]
# values = [190, 255, 337, 2799, 2801, 3733]
pairs = zip(values[1:-1:2], values[2:-1:2])
# pairs = [(255, 337), (2799, 2801)]
out = '\n'.join('%d..%d' % pair for pair in pairs)
# out = "255..337\n2799..2801"
Try this:
with open(filename, 'r') as f:
lines = f.readlines()
numbers = []
for row in lines:
numbers.extend(row.split('..'))
numbers = numbers[1:len(numbers)-1]
newLines = ['..'.join(numbers[idx:idx+2]) for idx in xrange(0, len(numbers), 2]
with open(filename, 'w') as f:
for line in newLines:
f.write(line)
f.write('\n')
Try this:
Read all of them into one list, split each line into two numbers, so you have one list of all your numbers.
Remove the first and last item from your list
Write out your list, two items at a time, with dots in between them.
Here's an example:
a = """190..255
337..2799
2801..3733
3734..5020
5234..5530
5683..6459
8238..9191
9306..9893"""
a_list = a.replace('..','\n').split()
b_list = a_list[1:-1]
b = ''
for i in range(len(a_list)/2):
b += '..'.join(b_list[2*i:2*i+2]) + '\n'
temp = []
with open('temp.txt') as ofile:
for x in ofile:
temp.append(x.rstrip("\n"))
for x in range(0, len(temp) - 1):
print temp[x].split("..")[1] +".."+ temp[x+1].split("..")[0]
x += 1
Maybe this will help:
def makeColumns(listOfNumbers):
n = int()
while n < len(listOfNumbers):
print(listOfNumbers[n], '..', listOfNumbers[(n+1)])
n += 2
def trim(listOfNumbers):
listOfNumbers.pop(0)
listOfNumbers.pop((len(listOfNumbers) - 1))
listOfNumbers = [190, 255, 337, 2799, 2801, 3733, 3734, 5020, 5234, 5530, 5683, 6459, 8238, 9191, 9306, 9893]
makeColumns(listOfNumbers)
print()
trim(listOfNumbers)
makeColumns(listOfNumbers)
I think this might be useful too. I am reading data from a file name list.
data = open("list","r")
temp = []
value = []
print data
for line in data:
temp = line.split("..")
value.append(temp[0])
value.append(temp[1])
for i in range(1,(len(value)-1),2):
print value[i].strip()+".."+value[i+1]
print value
After reading the data I split and store it in the temporary list.After that, I copy data to the main list value which have all of the data.Then I iterate from the second element to second last element to get the output of interest. strip function is used in order to remove the '\n' character from the value.
You can later write these values to a file Instead of printing out.

Categories