Shrink tuples in list of tuples in Python - list

I have a list of tuples. How can I drop some elements in all tuples? E.g.
[...,(23188,'Bob',1944,'Dentist','Houston'),(44512,'Charlie',1961,'Teacher','Boston'), ...]
should become
[...,('Bob',1944,'Houston'),('Charlie',1961,'Boston'), ...]

You can use like this.
>>>
>>> l1 = [(23188,'Bob',1944,'Dentist','Houston'),(44512,'Charlie',1961,'Teacher'
,'Boston')]
>>>
>>> import operator
>>> pickup = operator.itemgetter(1,2,4)
>>> map(pickup,l1)
[('Bob', 1944, 'Houston'), ('Charlie', 1961, 'Boston')]
>>>

Related

How to get two random numbers from a list of lists?

When I tried to generate two random numbers from lists of list and the two random numbers should be from two different lists in a list, I got two elements from the same list in a lists of list.
Example:
list1 = [[1,2,],[3,4],[5,6]]
import random
random.choice(random.sample(l,2))
output = [5, 6]
and
for random.sample(random.choice(l),2)
output = [2, 1]
I really didn't understand what you asked for, but if you want a random element from list of lists,
>>> import random
>>> from itertools import chain
>>> list1 = [[1,2,],[3,4],[5,6]]
>>> random.choice(list(chain.from_iterable(list1)))
4
>>> random.choice(list(chain.from_iterable(list1)))
3
>>> random.choice(list(chain.from_iterable(list1)))
1
What chain.from_iterable(iterable) does is, flatting the list of lists.
>>> list(chain.from_iterable(list1))
[1, 2, 3, 4, 5, 6]
https://docs.python.org/2/library/itertools.html#itertools.chain.from_iterable

Python 3.4: adding value to list if condition exists

i have a scenario like this one:
mainList = [[9,5],[17,3],[23,1],[9,2]]
secondaryList = [9,12,28,23,1,6,95]
myNewList = []
myNewList.append([[a,b] for a,b in mainList if a in secondaryList])
this, return me to me:
myNewList = [[9,5],[23,1],[9,2]]
but I need only the first occourance of "a". In other words I need to obtain:
myNewList = [[9,5],[23,1]]
How can I achieve this?
First of all:
myNewList = []
myNewList.append([[a,b] for a,b in mainList if a in secondaryList])
simply is the same as
myNewList = [[a,b] for a,b in mainList if a in secondaryList]
Then:
What you're building is functionally a python dictionary. Your two-element lists in mainList are the same as dict.items()!
So what you'd do is build a dict out of mainList (reversing it, because usually, you'd just save the last, not the first occurence):
mainDict = dict([reversed(mainList)])
Then you just make your new list:
myNewList = [ (key, mainDict[key]) for key in secondaryList ]
You can use a set to store the first elements and then check for existing the first element before adding the sub-lists :
>>> seen=set()
>>> l=[]
>>> for i,j in mainList:
... if i in secondaryList and i not in seen:
... seen.add(i)
... l.append([i,j])
...
>>> l
[[9, 5], [23, 1]]
Or you can use collections.defaultdict and deque with specifying its maxlen.But note that you need to loop over your list from end to start if you want the first occourance of a because deque will keep the last insert value :
>>> from collections import defaultdict
>>> from functools import partial
>>> d=defaultdict(partial(deque, maxlen=1))
>>> for i,j in mainList[::-1]:
... if i in secondaryList:
... d[i].append(j)
...
>>> d
defaultdict(<functools.partial object at 0x7ff672706e68>, {9: deque([5], maxlen=1), 23: deque([1], maxlen=1)})

python: copying list and appending in one step

I have a strange reaction of python (using 2.7) here. I am trying to copy a list and append something to the copy at the same time. Here is the code:
myList = [1]
>>> newList = list(myList).append(2)
>>> newList
>>> print newList
None
>>> type(newList)
<type 'NoneType'>
Why is it that I get a NoneType object instead of my appended list-copy?
I stumbled over this when I tried to take a list1 copy it as many times as a list2 and append the elements of list2 to the ones in list1.
>>> list1 = [1,2]
>>> list2 = [3,4]
>>> list3 = [list(list1).append(i) for i in list2]
>>> list3
[None, None]
I expected:
>>> list3
[[1,2,3],[1,2,4]]
Why is it None,None?
Thanks a lot!
You can do this by adding a extra line:
myList=[1]
myList.append(2);newList=myList
You can also extend (append )list directly like:
list1 = [1,2]
list2 = [3,4]
list1.extend(list2);list3=list1
If u dont want to alter then try this:
list1 = [1,2]
list2 = [3,4]
list3=list1;list3.extend(list2)
And also:
myList=[1]
newList=myList;newList.append(2)
The append function modifies a list and returns None. Newlist was None because append() modifies the list directly, rather than returning the modified list.
This code will create the new list and add to it in one step.
myList = [1]
newList = myList + [2]

Getting used indices of indexed terms in a sympy sum

Say I have variables x and y which are indexed
from sympy.tensor import IndexedBase
x = IndexedBase('x')`
And I have an expression like e = x[1] y[2] + x[5] y[10]
. I want to find all indices used by each of x and y. I'm looking for a function which might work like this: e.indices(y) = [2, 10] and e.indicies(x) = [1, 5]
Is there a way I can iterate through the terms x[i] y[j]? And if so, is there a way to split a product into terms and for each of those pull out which letter is being used and which index appears?
The following should get you headed in the right direction:
>>> from sympy.tensor import IndexedBase, Indexed
>>> from sympy import sift
>>> x = IndexedBase('x')
>>> y = IndexedBase('y')
>>> e = x[1]* y[2] + x[5]* y[10]
>>> e.atoms(IndexedBase)
set([y, x])
>>> e.atoms(Indexed)
set([x[5], y[10], x[1], y[2]])
>>> sifted = sift(_,lambda i: i.base)
>>> sifted[x]
[x[5], x[1]]
>>> sifted[y]
[y[10], y[2]]
>>> [i.indices for i in _]
[(10,), (2,)]
>>> flatten(_)
[10, 2]

appending a queryset to a list/tuple without evaluating it

According to the docs a queryset gets evaluated when list() is called on it.
Is there a way to append a list/tuple with a queryset instead of model objects? Is list() called for every operation on lists/tuples?
e.g:
foo= Foo.objects.all()
bar = Bar.objects.filter(enabled=True)
my_list = []
my_list.append(foo) <-- evaluates
my_list.extend(foo) <-- evaluates
my_tuple = ()
my_tuple = my_tuple + (foo,) <-- evaluates
# so I'm getting
[<Foo: ModelDescription>,<Foo: ModelDescription>,<Bar: ModelDescription>]
#but I want
[<Queryset: Foo>, <Queryset:Bar>]
This is either no longer true or perhaps the way you were checking the type of the elements was inadvertently triggering the evaluation.
To summarize, you can use append() or my_tuple = my_tuple + (foo,). If you try to just print these it will evaluate the QuerySet and output their contents but if you loop through these collections you can work with the actual QuerySet.
>>> a = Author.objects.filter()
>>> b = Book.objects.filter()
>>> type(a), type(b)
(<class 'django.db.models.query.QuerySet'>, <class 'django.db.models.query.QuerySet'>)
>>> l = []
>>> l.append(a)
>>> l.append(b)
>>> type(l[0]), type(l[1])
(<class 'django.db.models.query.QuerySet'>, <class 'django.db.models.query.QuerySet'>)
>>> for q in l:
... print type(q)
...
<class 'django.db.models.query.QuerySet'>
<class 'django.db.models.query.QuerySet'>
>>> my_tuple = ()
>>> my_tuple = my_tuple + (a,)
>>> type(my_tuple[0])
<class 'django.db.models.query.QuerySet'>
>>> len(l)
2
>>> len(my_tuple)
1
>>> print l
[[<Author: Author object>, '...(remaining elements truncated)...'], [<Book: Book object>,]]
>>> len(my_tuple)
1
>>> print my_tuple
([<Author: Author object>, '...(remaining elements truncated)...'],)
>>> len(my_tuple)
1
>>>