Python, need help parsing items from text file into list - python

I'm trying to parse items in a text file and store them into a list. The data looks something like this:
[(0, 0, 0), (1, 0, 0), (2, 0, 0), (3, 0, 0), (4, 0, 0), (5, 0, 0), (6, 0, 0)]
[(10, 3, 1), (11, 3, 1), (12, 3, 1), (13, 3, 1), (13, 4, 1)]
[(10, 3, 5), (11, 3, 5), (12, 3, 5), (13, 3, 5), (13, 4, 5), (13, 5, 5), (13, 6, 5)]
[(6, 13, 5), (7, 13, 5), (8, 13, 5), (8, 14, 5), (7, 14, 5), (6, 14, 5), (6, 14, 6)]
I was able to strip the "[" and "]" but couldn't store the rest of information into list as such format:
(x, y, z). Any help?
def dataParser(fileName):
zoneList=[]; zone=[]
input=open(fileName,"r")
for line in input:
vals = line.strip("[")
newVals = vals.strip("]\n")
print newVals
v=newVals[0:9]
zone.append(v)
input.close()
return zone

In this particular case, you can use ast.literal_eval:
>>> with open("list.txt") as fp:
... data = [ast.literal_eval(line) for line in fp if line.strip()]
...
>>> data
[[(0, 0, 0), (1, 0, 0), (2, 0, 0), (3, 0, 0), (4, 0, 0), (5, 0, 0), (6, 0, 0)], [(10, 3, 1), (11, 3, 1), (12, 3, 1), (13, 3, 1), (13, 4, 1)], [(10, 3, 5), (11, 3, 5), (12, 3, 5), (13, 3, 5), (13, 4, 5), (13, 5, 5), (13, 6, 5)], [(6, 13, 5), (7, 13, 5), (8, 13, 5), (8, 14, 5), (7, 14, 5), (6, 14, 5), (6, 14, 6)]]
It's the "safe" version of eval. It's not as general, though, for precisely that reason. If you're generating this input, you might want to look into a different way to save your data ("serialization"), whether using pickle or something like JSON -- there are lots of examples of using both you can find on SO and elsewhere.

You can do it without eval, using the string split method and the tuple constructor:
>>> st = "[(0,0,0), (1,0,0)]"
>>> splits = st.strip('[').strip(']\n').split(', ')
>>> splits
['(0,0,0)', '(1,0,0)']
>>> for split in splits:
... trimmed = split.strip('(').strip(')')
... tup = tuple(trimmed.split(','))
... print tup, type(tup)
...
('0', '0', '0') <type 'tuple'>
('1', '0', '0') <type 'tuple'>
>>>
From there, it's just appending to a list.

some might not like using eval() here, but you can do this in one line using it:
In [20]: lis=eval("[(0, 0, 0), (1, 0, 0), (2, 0, 0), (3, 0, 0), (4, 0, 0), (5, 0, 0), (6, 0, 0)]")
In [23]: lis
Out[23]: [(0, 0, 0), (1, 0, 0), (2, 0, 0), (3, 0, 0), (4, 0, 0), (5, 0, 0), (6, 0, 0)]
using a text file:
In [44]: with open('data.txt') as f:
....: lis=[eval(x.strip()) for x in f]
....: print lis
....:
....:
[[(0, 0, 0), (1, 0, 0), (2, 0, 0), (3, 0, 0), (4, 0, 0), (5, 0, 0), (6, 0, 0)], [(10, 3, 1), (11, 3, 1), (12, 3, 1), (13, 3, 1), (13, 4, 1)], [(10, 3, 5), (11, 3, 5), (12, 3, 5), (13, 3, 5), (13, 4, 5), (13, 5, 5), (13, 6, 5)], [(6, 13, 5), (7, 13, 5), (8, 13, 5), (8, 14, 5), (7, 14, 5), (6, 14, 5), (6, 14, 6)]]

The following is a bad idea if you're getting this data from any source that you don't trust completely, but if the data will always be in this format (and only contain numbers as the elements) something like this is quite straightforward:
collect = []
for line in input:
collect.append(eval(line))

The other answers work just fine and are a simple solution to this specific problem. But I am assuming that if you were having problems with string manipulation, then a simple eval() function won't help you out much the next time you have this problem.
As a general rule, the first thing you want to do when you are approached with a problem like this, is define your delimiters.
[(0, 0, 0), (1, 0, 0), (2, 0, 0), (3, 0, 0), (4, 0, 0), (5, 0, 0), (6, 0, 0)]
Here you can see that "), (" is a potential delimiter between groups and a simple comma (",") is your delimiter between values. Next you want to see what you need to remove, and as you pointed out, brackets ("[" and "]") provide little information. We can also see that because we are dealing with numeric values, all spacing gives us little information and needs to be removed.
Building on this information, I set up your dataParser function in a way that returns the values you were looking for:
fileName= "../ZoneFinding/outputData/zoneFinding_tofu_rs1000.txt"
def dataParser(fileName):
with open(fileName,"r") as input
zoneLst = []
for line in input:
#First remove white space and the bracket+parenthese combos on the end
line = line.replace(" ","").replace("[(","").replace(")]","")
#Now lets split line by "),(" to create a list of strings with the values
lineLst = line.split("),(")
# At this point lineLst = ["0,0,0" , "1,0,0", "2,0,0", ...]
#Lastly, we will split each number by a "," and add each to a list
zone = [group.split(",") for group in lineLst]
zoneLst.append(zone)
return zoneLst
In the example above, all of the values are stored as strings. You could also replace the
definition of zone with the code below to store the values as floats.
zone = [ [float(val) for val in group.split(",")] for group in lineLst]

Related

How to get unique combinations of pairs in nested tuples?

I have a list of pairs of the form [(tuple1), (tuple2)],where the first tuple has variable length and the second has length 1.
Example:
[((0, 1, 2), 0),
((3, 4, 5), 0),
((12,), 1),
((0, 1, 4, 7), 1),
((12,), 1),
((3, 4, 5), 0)]
I want set(pairs), where tuple1_pair_X = tuple1_pair_Y && tuple2_pair_X = tuple2_pair_Y and not all the possible combinations of tuple1 elements with tuple2.
Desired Output:
[((0, 1, 2), 0),
((3, 4, 5), 0),
((12,), 1),
((0, 1, 4, 7), 1)]
If you want to keep order of your list:
lst = [((0, 1, 2), 0),
((3, 4, 5), 0),
((12,), 1),
((0, 1, 4, 7), 1),
((12,), 1),
((3, 4, 5), 0)]
sorted(set(lst), key=lst.index)
outputs:
[((0, 1, 2), 0),
((3, 4, 5), 0),
((12,), 1),
((0, 1, 4, 7), 1)]
I guess simply using the set() command on the original list of tuples should work and give your desired output.
tup_list = [((0, 1, 2), 0), ((3, 4, 5), 0),((12,), 1),((0, 1, 4, 7), 1),((12,), 1),((3, 4, 5), 0)]
output = list(set(tup_list))

Merge list of list with duplicates

Input list
[(1, 0, 3), '21:40:44', (1, 3, 9), (1, 4, 6), '.273']
[(1, 0, 3), '21:43:37', (1, 3, 9), (1, 4, 6), '.060']
[(1, 0, 3), '21:45:27', (1, 3, 9), (1, 4, 6), '.410']
And the result should be like:
[(1, 0, 3), ['21:40:44', '21:43:37', '21:45:27'], (1, 3, 9), (1, 4, 6), ['.273', '.060', '.410']
The goal is to reduce the duplicates, the unique elements in a column should be stored in a list.
How about using zip. It will merge the 3 list and give you output with duplicates. later use set to remove duplicates. and since you don not want list of tuple for single element only, use list(set(x))[0] if len(set(x))==1 else list(set(x))
a=[(1, 0, 3), '21:40:44', (1, 3, 9), (1, 4, 6), '.273']
b=[(1, 0, 3), '21:43:37', (1, 3, 9), (1, 4, 6), '.060']
c=[(1, 0, 3), '21:45:27', (1, 3, 9), (1, 4, 6), '.410']
l=[list(set(x))[0] if len(set(x))==1 else list(set(x)) for x in list(zip(a,b,c))]
print(l)
>>>[(1, 0, 3), ['21:45:27', '21:40:44', '21:43:37'], (1, 3, 9), (1, 4, 6), ['.060', '.273', '.410']]
the simplest way is this:
in_data = [
[(1, 0, 3), '21:40:44', (1, 3, 9), (1, 4, 6), '.273'],
[(1, 0, 3), '21:43:37', (1, 3, 9), (1, 4, 6), '.060'],
[(1, 0, 3), '21:45:27', (1, 3, 9), (1, 4, 6), '.410']
]
res = []
for i in range(len(in_data[0])):
data = list(set([x[i] for x in in_data ]))
data = data[0] if len(data) == 1 else data
res.append(data)
print(res)
>>> [(1, 0, 3), ['21:43:37', '21:40:44', '21:45:27'], (1, 3, 9), (1, 4, 6), ['.273', '.060', '.410']]

Python: Create route from Arcs

I am working on a capacitated vehicle routing problem and have found an optimal solution with the following set of arcs on my graph active:
[(0, 1),
(0, 4),
(0, 5),
(0, 6),
(0, 7),
(0, 10),
(1, 0),
(2, 13),
(3, 9),
(4, 12),
(5, 0),
(6, 14),
(7, 8),
(8, 0),
(9, 0),
(10, 11),
(11, 0),
(12, 3),
(13, 0),
(14, 2)]
the list is called arcsDelivery.
I would like to restructure this list to come to my found routes stored in the list routesdelivery:
[[0,1,0],[0,4,12,3,9,0],[0,5,0],[0,6,14,2,13,0],[0,7,8,0],[0,10,11,0]]
However, I have been struggeling to do so, anyone with some helpful tips?
Here is a way to do it (considering that the arcsdelivery list is sorted in ascending order based on the first element of each tuple):
def findTuple(elem):
for t in arcsDelivery:
if t[0]==elem:
return t
return None
arcsDelivery = [(0, 1),
(0, 4),
(0, 5),
(0, 6),
(0, 7),
(0, 10),
(1, 0),
(2, 13),
(3, 9),
(4, 12),
(5, 0),
(6, 14),
(7, 8),
(8, 0),
(9, 0),
(10, 11),
(11, 0),
(12, 3),
(13, 0),
(14, 2)]
routesDelivery = []
startRoutes = len(list(filter(lambda elem: elem[0]==0, arcsDelivery)))
for i in range(startRoutes):
tempList = []
currentTuple = arcsDelivery[i]
tempList.append(currentTuple[0])
tempList.append(currentTuple[1])
while True:
if currentTuple[1]==0:
break
else:
nextTuple = findTuple(currentTuple[1])
currentTuple = nextTuple
tempList.append(currentTuple[1])
routesDelivery.append(tempList)
print(routesDelivery)
Output:
[[0, 1, 0], [0, 4, 12, 3, 9, 0], [0, 5, 0], [0, 6, 14, 2, 13, 0], [0, 7, 8, 0], [0, 10, 11, 0]]

Python matching

I have 3 great lists and I would like to make 1: 1: 1 relationships with them. To be clearer I will show the lists:
lstA= [[[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (16, 0)], [(8, 1), (9, 1), (10, 1), (16, 0)], [(11, 1), (12, 1), (13, 1), (14, 1), (15, 1), (16, 0)]], [[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (17, 0)], [(8, 1), (9, 1), (10, 1), (17, 0)], [(11, 1), (12, 1), (13, 1), (14, 1), (15, 1), (17, 0)]], [[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (18, 0)], [(8, 1), (9, 1), (10, 1), (18, 0)], [(11, 1), (12, 1), (13, 1), (14, 1), (15, 1), (18, 0)]], [[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (19, 0)], [(8, 1), (9, 1), (10, 1), (19, 0)], [(11, 1), (12, 1), (13, 1), (14, 1), (15, 1), (19, 0)]]]
lstB= [[[1, 1, 1, 1, 1, 1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, 1, 1, -1]], [[1, 1, 1, 1, 1, 1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, 1, 1, -1]], [[1, 1, 1, 1, 1, 1, 1, 1, -3], [1, 1, 1, -1], [1, 1, 1, 1, 1, -2]], [[1, 1, 1, 1, 1, 1, 1, 1, -3], [1, 1, 1, -1], [1, 1, 1, 1, 1, -2]]]
lstC= [[[8], [3], [5]], [[8], [3], [5]], [[8], [3], [5]], [[8], [3], [5]]]
Each of these lists consists of 4 lists, which at the same time, are composed of 3 lists. I need to match and print each element of a list with the one corresponding to the same position of the other lists:
As an example, the first matched element will be:
[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (16, 0)]), [1, 1, 1, 1, 1, 1, 1, 1, -2], [8]
The second matched element will be:
[(8, 1), (9, 1), (10, 1), (16, 0)], [1, 1, 1, -1], [3]
Any suggestions to make this?
You could use zip, as suggested by Julien and Juanpa in the comments, but then you'd have to flatten lists:
for i in range(len(lstA)):
for elt in zip(lstA[i], lstB[i], lstC[i]):
print elt
Instead, you could also use nested for loops:
for i in range(len(lstA)):
for j in range(len(lstA[i])):
print lstA[i][j], lstB[i][j], lstC[i][j]
For both solutions, if there are instances where the lists have different numbers of elements, you'll run into trouble.

find all elements and indices larger than threshold in list of lists

I have a list of lists like:
j=[[1,2,3],[4,5,6],[7,8,9,10],[11,12,13,14,15]]
and I want to get a list of all elements from the list of lists larger than a certain threshold. I know when having a list there is the Syntax:
k=[1,2,3,4,5,6,7]
k2=[i for i in k if i>5]
k2=[6,7]
Is there a similar way when having a lists of lists as an Input?
Is it additionally possible to get the indices of the elements larger than that threshold?
Is this what you mean?
In [3]: l1 = [[1,2,3],[4,5,6],[7,8,9,10],[11,12,13,14,15]]
In [4]: [e for l2 in l1 for e in l2 if e>5]
Out[4]: [6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
To get the index (of the inner lists), you can use enumerate:
In [5]: [(i2, e) for l2 in l1 for i2, e in enumerate(l2) if e>5]
Out[5]:
[(2, 6),
(0, 7),
(1, 8),
(2, 9),
(3, 10),
(0, 11),
(1, 12),
(2, 13),
(3, 14),
(4, 15)]
If you want the indices in a separate list (un)zip:
In [6]: list(zip(*[(i2, e) for l2 in l1 for i2, e in enumerate(l2) if e>5]))
Out[6]: [(2, 0, 1, 2, 3, 0, 1, 2, 3, 4), (6, 7, 8, 9, 10, 11, 12, 13, 14, 15)]
[You don't need the list call if you're using Python 2]. A similar approach will give you indexes into both the outer and inner lists:
In [7]: [((i1,i2), e) for (i1,l2) in enumerate(l1) for i2, e in enumerate(l2) if e>5]
Out[7]:
[((1, 2), 6),
((2, 0), 7),
((2, 1), 8),
((2, 2), 9),
((2, 3), 10),
((3, 0), 11),
((3, 1), 12),
((3, 2), 13),
((3, 3), 14),
((3, 4), 15)]
or, unzipped:
In [8]: idx, items = list(zip(*[((i1,i2), e) for (i1,l2) in enumerate(l1)
for i2, e in enumerate(l2) if e>5]))
In [8]: idx
Out[8]:
((1, 2),
(2, 0),
(2, 1),
(2, 2),
(2, 3),
(3, 0),
(3, 1),
(3, 2),
(3, 3),
(3, 4))
In [9]: items
Out[9]: (6, 7, 8, 9, 10, 11, 12, 13, 14, 15)

Categories