I have a function that ends up producing this:
exList=[([('Community Chest', 1), ('Jail', 1)], array([10, 17])), ([('Jail', 1), ('Chance', 1)], array([10, 22]))]
As you can see, it is a list and element i.e.
[('Community Chest', 1), ('Jail', 1)], array([10, 17])
within a tuple.
I've tried removing all parentheses like this:
for element in exList:
temp = ""
for ch in element:
if ch not in SYMBOLS:
temp += ch
results.append(temp)
print(results)
But it causes problems because the above code only works on a tuple, and not a list (I know, it's really confusing).
What I ultimately need, is to remove the outmost parentheses in order to get
this:
exList=[[('Community Chest', 1), ('Jail', 1)], array([10, 17]), [('Jail', 1), ('Chance', 1)], array([10, 22])]
As can you see, I want to remove the outermost parentheses.
Could you guys point me in the right direction?
Use a list comprehension and the itertools module:
print [i for i in itertools.chain(*exList)]]
For you to remove the out side parentheses in:
exList=[([('Community Chest', 1), ('Jail', 1)], array([10, 17])), ([('Jail', 1), ('Chance', 1)], array([10, 22]))]
Simply name a new list and use numpy to make an array out of each element in the list:
newlist=np.array(lists[0])
And do so for every tuple within the list.
Related
I am learning to code in python, and have written the following code to solve the two sum problem in a list.
My approach is as follows :
Take up an element in the list L
subtract the element value from the target sum
Check if this value is there anywhere in the list
If it is there add its index it to a new list and remove this value
from the original list L
My code runs well if I remove the 'remove' command but gives double results. Please help me in identifying the error.
l=[]
def two_sum(l,sval):
result=[]
for i in range(len(l)):
new=sval-l[i]
if new in l:
result=result+[(i,l.index(new))]
l.remove(new)
return(result)
I guess list index out of range is the Error that you receive. The reason is that you should never remove item when iterate a list in for loop: the list has been shortened because the corresponding index in range (0, Len(l)) was removed.
I think a while loop with two indicators serve better for this purpose. Try this:
def two_sum(l,sval):
i=0
j=0
result=[]
while i<len(l):
new=sval-l[i]
if new in l[j:]:
result=result+[(i,l.index(new))]
l[i], l[j]=l[j],l[i]
j+=1
i+=1
return result, l[j:]
So if you test:
l=list(np.arange(0,10,1))
two_sum(l,10)
it returns:
([(1, 9), (2, 8), (3, 7), (4, 6), (5, 5)], [0, 6, 7, 8, 9])
Where [(1, 9), (2, 8), (3, 7), (4, 6), (5, 5)] are the pairs
and [0, 6, 7, 8, 9] is the original list with summed objects removed.
Plus I guess it is slightly more efficient than the codes you provided: notice that the line if new in l[j:]: omit items that have been looped, so that it returns a summed pair only once.
I am brand new to python and coding in general. I'm actually a Cinema 4D artist. C4D has a built in python script manager. I will do my best to explain what I'm trying for.
I have a sphere. The sphere is broken up into points. I have calculated the distance each point on the sphere is away from a different object. I have made a list of all these calculated distances. I would like to make a new array of the index and the corresponding distance calculation. How do I combine the two lists into a new array? Mock example below -
def main():
pointdistance = [150.2, 2.3, 5.5, 145.2, 30.4, 22]
indices = list(range(len(pointdistance)))
print indices
It returns the correct number of indices needed [0,1,2,3,4,5]
my desired result would look like a combination - something like this:
preweight = [(0,150.2)(1,2.3)(2,5.5)(3,145.2)(4,30.4)(5,22)]
For bonus I would like to dynamically sort the new "preweight" array based on the distance calculation. So as I move the object around the array sorts from closest point to furtherest point. Kinda like this:
postweight = [(1,2.3)(2,5.5)(5,22)(4,30.4)(3,145.2)(1,150.2)]
Thanks in advance. I am really enjoying the help this site provides.
Use enumerate(..). When called on a list and iterated over, it returns elements of the list as a tuple of (index, element).
For the second half of your question, use sorted(.., key=<func>). sorted(..) when called with a key= will use the value returned by the function applied on the item for sorting. In your specific case, <func> would be something that would take an element and return the second item of the tuple. Something like: lambda x: x[1]
>>> pointdistance = [150.2, 2.3, 5.5, 145.2, 30.4, 22]
>>> list(enumerate(pointdistance))
[(0, 150.2), (1, 2.3), (2, 5.5), (3, 145.2), (4, 30.4), (5, 22)]
>>> sorted(enumerate(pointdistance), key=lambda x: x[1])
[(1, 2.3), (2, 5.5), (5, 22), (4, 30.4), (3, 145.2), (0, 150.2)]
To add to SuperSaiyan's answer, the built-in zip provides a more robust tool for solving all similar problems. While enumerate simply pairs a list of elements with their indexes automatically, zip requires that you provide a series of iterables that it will group together:
obj_labels = ['a', 'b', 'c', 'd']
obj_values = [1, 4, 7, 3]
paired = zip(obj_labels, obj_values)
print(paired) # gives: [('a', 1), ('b', 4), ('c', 7), ('d', 3)]
ordered = sorted(paired, key=lambda pair: pair[1])
print(ordered) # gives: [('a', 1), ('d', 3), ('b', 4), ('c', 7)]
However zip also allows you to do some other cool things like grouping more than two iterables, and "unzipping" a list elements that are equal length pairs. Continuing from the previous example:
# we can "unzip" our pairs like this
unzipped = zip(*paired)
# they come out as tuples
l1 = list(unzipped[0])
l2 = list(unzipped[1])
# check that we've unzipped
assert l1 == obj_labels
assert l2 == obj_values
# add more data to our paired list
obj_indexes = range(len(obj_values))
paired_len3 = zip(obj_labels, obj_indexes, obj_values)
ordered_len3 = sorted(paired_len3, key=lambda pair: pair[2])
print(ordered_len3) # gives: [('a', 0, 1), ('d', 3, 3), ('b', 1, 4), ('c', 2, 7)]
I want to "zip" char and list in Python:
An example:
char = '<'
list = [3, 23, 67]
"zip"(char, list)
>>> [('<', 3), ('<', 23), ('<', 67)]
How I'm using itertools.repeat():
itertools.izip(itertools.repeat(char, len(list)), list)
>>>[('<', 3), ('<', 23), ('<', 67)]
It works, but it so interesting to find more pythonic solution.
You don't need itertools here.
Using list comprehension:
>>> char = '<'
>>> lst = [3, 23, 67]
>>> [(char, n) for n in lst]
[('<', 3), ('<', 23), ('<', 67)]
BTW, don't use list as a variable name. It shadows builtin function list.
[(char, i) for i in list]
Naming your list as "list" is probably not a good idea btw., as this shadows the constructor for the internal list type.
If you want something equivalent to your use of itertools - using lazy generation for iteration - then you can use generator expressions. The syntax is pretty much equivalent to list comprehensions except you enclose the expression with paranthesis.
>>> c = '<'
>>> l = [3, 23, 67]
>>> my_gen = ((c, item) for item in l)
>>> for item in my_gen:
... print item
...
('<', 3)
('<', 23)
('<', 67)
For more info, here's the PEP that explains it: http://www.python.org/dev/peps/pep-0289/
If char is only ever going to be reused for all pairings, just use a list comprehension:
>>> [(char, i) for i in lst]
[('<', 3), ('<', 23), ('<', 67)]
If char is a string of characters, and you wanted to cycle through them when pairing (like zip() would for the shortest length sequence), use itertools.cycle():
>>> from itertools import cycle
>>> chars = 'fizz'
>>> lst = range(6)
>>> zip(chars, lst)
[('f', 0), ('i', 1), ('z', 2), ('z', 3)]
>>> zip(cycle(chars), lst)
[('f', 0), ('i', 1), ('z', 2), ('z', 3), ('f', 4), ('i', 5)]
Note how the characters of the string 'fizz' are reused to pair up with the numbers 4 and 5; they'll continue to be cycled to match any length list (which must be finite).
If you really want to use zip, here is how :
l = [3, 23, 67]
zip('<' * len(l), l)
[('<', 3), ('<', 23), ('<', 67)]
In further details, itertools.repeat(char, len(list)) is quite similar in result to '<' * 3. Also, both work with zip (you could write zip(itertools.repeat(char, len(list)), l)), too).
I have the following list of tuples:
a = [(1, 2), (2, 4), (3, 1), (4, 4), (5, 2), (6, 8), (7, -1)]
I would like to select the elements which second value in the tuple is increasing compared to the previous one. For example I would select (2, 4) because 4 is superior to 2, in the same manner I would select (4, 4) and (6, 8).
Can this be done in a more elegant way than a loop starting explicitly on the second element ?
To clarify, I want to select the tuples which second elements are superior to the second element of the prior tuple.
>>> [right for left, right in pairwise(a) if right[1] > left[1]]
[(2, 4), (4, 4), (6, 8)]
Where pairwise is an itertools recipe you can find here.
You can use a list comprehension to do this fairly easily:
a = [a[i] for i in range(1, len(a)) if a[i][1] > a[i-1][1]]
This uses range(1, len(a)) to start from the second element in the list, then compares the second value in each tuple with the second value from the preceding tuple to determine whether it should be in the new list.
Alternatively, you could use zip to generate pairs of neighbouring tuples:
a = [two for one, two in zip(a, a[1:]) if two[1] > one[1]]
You can use enumerate to derive indices and then make list comprehension:
a = [t[1] for t in enumerate(a[1:]) if t[1][1] > a[t[0]-1][1]]
You can use list comprehension
[i for i in a if (i[0] < i[1])]
Returns
[(1, 2), (2, 4), (6, 8)]
Edit: I was incorrect in my understanding of the question. The above code will return all tuples in which the second element is greater than the first. This is not the answer to the question OP asked.
I have an input list for example :
mylist = [('a', [(2, 4), (0, 5)]), ('b', [(3, 9), (1, 1)]), ("'", None), ('c', [(1,7), (2, 8)])]
I have to carry out comparisons between the values in the list. The item like (2,4) denotes a range. The 'None' entry in the list is like a boundary. The comparisons take place within the boundaries. So here, comparisons will be between a and b first. The comparison is basically between the values given with different conditions like if they are overlapping or not, since they are ranges. So the ranges change after comparing with the neighbour's ranges.
if within the boundary : (something like "if ! None : then continue")
do the comparisons between the items inside the boundary
if None :
move to next boundary
do the comparisons between the items inside the next boundary
Comparison is with simple rules for example, say comparing (2,4) and (3,9) then these two overlap partially so the common between them is chosen. Hence, the result is (3,4).
I have written the code for all the comparison rules but I tried them without boundaries. But they should be within boundaries. And I could not express the boundaries in code. Thank you.
You can group items by testing their second values is None or not, using itertools.groupby.
>>> import itertools
>>> mylist
[('a', [(2, 4), (0, 5)]), ('b', [(3, 9), (1, 1)]), ("'", None), ('c', [(1, 7), (2, 8)])]
>>> grp = itertools.groupby(mylist, lambda i: i[1] is None)
>>> res = [tuple(i[1]) for i in grp if not i[0]] #use parantheses for faster generator expression.
>>> pprint.pprint(res)
[(('a', [(2, 4), (0, 5)]), ('b', [(3, 9), (1, 1)])),
(('c', [(1, 7), (2, 8)]),)]
Now you can use a simple for loop for comparisions:
for item in res:
#do comparisons
Building on the code from your other questions, if you want to handle each part of res separately and accumulate the results, you can do it like this (using the method from #utdemir's answer):
from operator import itemgetter
print "Original List"
print '\n'.join(str(l) for l in phonemelist)
grp = itertools.groupby(phonemelist, itemgetter(1))
res = [tuple(v) for k, v in grp if k]
print '\n'.join(str(l) for l in res)
newlists = []
# for each part between the markers
for item in res:
# update the ranges and add it to the overall list
newlists.append(update_ranges(item))
print "\n after applying co-articulation rules"
print '\n\n'.join('\n'.join(str(i) for i in l) for l in newlists)