Related
Code newbie here, and I am creating a project in Python.
I have a class called ExpressionTree which is, an N-ary expression tree, such that each node is not merely restricted to having only two children; it can have more than 2, but not less than 2.
The only operators I would use in this tree are "+" and "-" (but the code should work for any operator).
All leaves are either a single letter string, or an integer, and all parents are either "+" or "-".
The method I am trying to create is called create_tree, which takes in a list called lst, for which the type is: List[List[Union[int, str]]], and returns a successfully created ExpressionTree that was made from the parameter: lst.
Each list in lst represents a level, but for each operator in the list, the next lists are the children of each operator. For example, if lst = [[+], [+, +], [1, 2], [3, 4]], then the Tree should look something like:
Tree 1
On a more nested example, if I were to run create_class([[+], [3, +, +], [5, *], [b, c], [6, a]]), the Tree I should be getting is:
Tree 2
I know that a Queue would be very useful, but I do not know where to start.
I don't think this code necessarily would need recursion, but it could work with it as well if implemented correctly.
Any help with the code is immensely appreciated.
Thanks in advance!
You can recursively partition the list to build the tree:
from collections import deque
def to_tree(d):
k = [[i, [] if i not in {'+', '*'} else d.popleft()] for i in d.popleft()]
for i in range(len(k)):
if k[i][0] in {'+', '*'}:
d = deque([k[i][-1], *d])
k[i][-1] = k[i][-1] if len(d) == 1 else to_tree(d)
return [[a, b] if b else a for a, b in k]
lst = [['+'], ['+', '+'], ['1', '2'], ['3', '4']]
lst1 = [['+'], ['3', '+', '+'], ['5', '*'], ['b', 'c'], ['6', 'a']]
lst2 = [['+'], ['3', 'c', '+'], ['5', 'a']]
print(to_tree(deque(lst)))
print(to_tree(deque(lst1)))
print(to_tree(deque(lst2)))
Output:
[['+', [['+', ['1', '2']], ['+', ['3', '4']]]]]
[['+', ['3', ['+', ['5', ['*', ['6', 'a']]]], ['+', ['b', 'c']]]]]
[['+', ['3', 'c', ['+', ['5', 'a']]]]]
I have seen a variety of answers on here, but none that quite answered my question. I am trying to convert the following list
list = ['A', '2', '8', 'B', '3']
to the following:
list = ['A', 2, 8, 'B', 3]
I want to keep the strings as strings but convert the strings to ints where possible.
I know I could do something like:
list = [int(i) for i in list]
if it were just numbers, but I am unsure how to do it when it is mixed.
There's always try/except:
oldlist = ['A', '2', '8', 'B', '3']
newlist = []
for x in oldlist:
try:
newlist.append(int(x))
except ValueError:
newlist.append(x)
newlist
# ['A', 2, 8, 'B', 3]
You can use str.isdigit():
>>> l = ['A', '2', '8', 'B', '3']
>>> [int(x) if x.isdigit() else x for x in l]
['A', 2, 8, 'B', 3]
Taking negative numbers into account:
>>> l = ['A', '2', '8', 'B', '-3']
>>> [int(x) if x.isdigit() or x.startswith('-') and x[1:].isdigit() else x for x in l]
>>> ['A', 2, 8, 'B', -3]
I would just extract the conversion into a function.
def int_if_possible(value):
try:
return int(value)
except (ValueError, TypeError):
return value
int_list = [int_if_possible(i) for i in int_list]
Also I renamed your list to int_list, so that we can still use the list constructor if required.
You can use try , except block
lst1 = ['A', '2', '8', 'B', '3']
lst2 = []
for i in lst1:
try:
lst2.append(int(i))
except ValueError:
lst2.append(i)
print lst2
I have a list
A = [['1'],['1','2'],['1','2','3','1','2'],['3','3','3']]
and I want to make my list to
A = [['1'],['1','2'],['1','2','3'],['3']]
ie I want to remove duplicate elements within the elements in a list ..
One-liner (If order doesn't matter) :
A = [['1'],['1','2'],['1','2','3','1','2'],['3','3','3']]
A = [list(set(a)) for a in A]
print(A) # => [['1'], ['2', '1'], ['3', '2', '1'], ['3']]
One-liner (If order matters) :
A = [['1'],['1','2'],['1','2','3','1','2'],['3','3','3']]
A = [sorted(set(a), key=a.index) for a in A]
print(A) # => [['1'], ['1', '2'], ['1', '2', '3'], ['3']]
A functional version, with functools:
>>> import functools
>>> A = [['1'],['1','2'],['1','2','3','1','2'],['3','3','3']]
>>> print ([functools.reduce(lambda result,x:result if x in result else result+[x], xs, []) for xs in A])
[['1'], ['1', '2'], ['1', '2', '3'], ['3']]
The lambda function adds an element to the result list only if that element is not present in the list. Not very efficient, but keeps the order of elements.
Also note that with Python 2, you don't need to import functools: reduce is a builtin function.
You can use a generator:
def remove_dups(l):
for a in l:
new_l = []
for b in a:
if b not in new_l:
new_l.append(b)
yield new_l
A = [['1'],['1','2'],['1','2','3','1','2'],['3','3','3']]
print(list(remove_dups(A)))
Output:
[['1'], ['1', '2'], ['1', '2', '3'], ['3']]
I have the two list dictionary like this
obj1 = [mydict['obj1'],mydict['obj2'],mydict['obj3'],mydict['obj4']]
obj2 = [mydict['obj1'],mydict['obj2'],mydict['obj3'],mydict['obj4'], mydict['obj5'] ]
Now i want that
Count the number of elements in each list
Then based on whichever is greater then get that list of objects
I want a single list which conatins the above two list of(list of) dictionaries based on the higher number of elements so that i cause something like this
mylist = myfunc(objects1, objects2 )
mylist should be a list like [objects1, objects2] depending upon who has greater number of objects.
what is the best way to do that with less lines of code
Something like EDIT
mylist = sorted([obj1, obj2], key=lambda a: len(a), reverse=True)
There's no need to use a lambda function if it's just going to call a function anyway.
>>> objects1 = [1, 2, 3]
>>> objects2 = ['1', '2', '3', '4']
>>>
>>> mylist = [objects1, objects2]
>>> max(mylist, key=len)
['1', '2', '3', '4']
>>> sorted(mylist, key=len, reverse=True)
[['1', '2', '3', '4'], [1, 2, 3]]
objects1 = [1, 2, 3]
objects2 = ['1', '2', '3', '4']
mylist = [objects1, objects2]
mylist.sort(key=len, reverse=True)
print mylist
[['1', '2', '3', '4'], [1, 2, 3]]
I want to find the location(s) of a specific item in a list of lists. It should return a list of tuples, where each tuple represents the indexes for a specific instance of the item. For example:
list = [['1', '2', '4', '6'], ['7', '0', '1', '4']]
getPosition('1') #returns [(0, 0), (1, 2)]
and getPosition('7') #returns [(1,0)]
If you want something that will both
find duplicates and
handle nested lists (lists of lists of lists of ...)
you can do something like the following:
def get_positions(xs, item):
if isinstance(xs, list):
for i, it in enumerate(xs):
for pos in get_positions(it, item):
yield (i,) + pos
elif xs == item:
yield ()
Testing this:
>>> xs = [['1', '2', '4', '6'],
... ['7', '0', '1', '4'],
... [ [ '0', '1', '1'], ['1']]
... ]
>>> print list(get_positions(xs, '1'))
[(0, 0), (1, 2), (2, 0, 1), (2, 0, 2), (2, 1, 0)]
It looks likes you want, for a list of sublists and a given item, to return a list of pairs where each pair is (the index of the sublist, the index of the item within the sublist). You can do that using list comprehensions and Python's built in enumerate() function:
def getPosition(list, item):
return [(i, sublist.index(item)) for i, sublist in enumerate(list)]
Edit: See #scribble's answer above/below.
def getPosition(list, item):
return [(i, sublist.index(item)) for i, sublist in enumerate(list)
if item in sublist]
def get_positions(xs, target):
return [(i,e.index(target)) for i,e in enumerate(xs)]
That's a good starting point. Presumably you have some sort of class such as
class SomeClass:
def __init__(self):
self.xs = [['1','2','4','6'], ['7','0','1','4']]
def get_positions(self, target):
return [(i,e.index(target)) for i,e in enumerate(self.xs)]
which in this case would let you say
model = SomeClass()
model.get_position(1) # returns [(0,0), (1,2)]
Note that in both cases you'll get an exception if your target isn't in every one of your sublists. The question does not specify whether this is the desired behavior.
If you don't want a exception if the item is not in the list try this. Also as a generator because they are cool and versatile.
xs = [['1', '2', '4', '6'], ['7', '0', '1', '4']]
def get_positions(xs, item):
for i, xt in enumerate( xs ):
try: # trying beats checking
yield (i, xt.index(item))
except ValueError:
pass
print list(get_positions(xs, '1'))
print list(get_positions(xs, '6'))
# Edit for fun: The one-line version, without try:
get_positions2 = lambda xs,item: ((i,xt.index(item)) for i, xt in enumerate(xs) if item in xt)
print list(get_positions2(xs, '1'))
print list(get_positions2(xs, '6'))
A while ago I wrote a library for python to do list matching that would fit the bill pretty well. It used the tokens ?, +, and * as wildcards, where ? signifies a single atom, + is a non-greedy one-or-more, and * is greedy one-or-more. For example:
from matching import match
match(['?', 2, 3, '*'], [1, 2, 3, 4, 5])
=> [1, [4, 5]]
match([1, 2, 3], [1, 2, 4])
=> MatchError: broken at 4
match([1, [2, 3, '*']], [1, [2, 3, 4]])
=> [[4]]
match([1, [2, 3, '*']], [1, [2, 3, 4]], True)
=> [1, 2, 3, [4]]
Download it here: http://www.artfulcode.net/wp-content/uploads/2008/12/matching.zip
Here is a version without try..except, returning an iterator and that for
[['1', '1', '1', '1'], ['7', '0', '4']]
returns
[(0, 0), (0, 1), (0, 2), (0, 3)]
def getPosition1(l, val):
for row_nb, r in enumerate(l):
for col_nb in (x for x in xrange(len(r)) if r[x] == val):
yield row_nb, col_nb
The most strainghtforward and probably the slowest way to do it would be:
>>> value = '1'
>>> l = [['1', '2', '3', '4'], ['3', '4', '5', '1']]
>>> m = []
>>> for i in range(len(l)):
... for j in range(len(l[i])):
... if l[i][j] == value:
... m.append((i,j))
...
>>> m
[(0, 0), (1, 3)]
Here is another straight forward method that doesn't use generators.
def getPosition(lists,item):
positions = []
for i,li in enumerate(lists):
j = -1
try:
while True:
j = li.index(item,j+1)
positions.append((i,j))
except ValueError:
pass
return positions
l = [['1', '2', '4', '6'], ['7', '0', '1', '4']]
getPosition(l,'1') #returns [(0, 0), (1, 2)]
getPosition(l,'9') # returns []
l = [['1', '1', '1', '1'], ['7', '0', '1', '4']]
getPosition(l,'1') #returns [(0, 0), (0, 1), (0,2), (0,3), (1,2)]