Python lists: join list by index - python

I'd like to join a list into a string by index in Python 3.3. I can do it for items the follow each other, but I would like to access it by index only.
this works:
list = ['A', 'B', 'C', 'D']
partList = "".join(list[1:3])
-> BC
But how can I achieve this (it doesn't work):
list = ['A', 'B', 'C', 'D']
partList = "".join(list[0,3])
-> AD

You can't slice lists into arbitrary chunks using slice notation. Probably your best bet for the general case is to use a list of indices to build a list comprehension.
mylist = ['A', 'B', 'C', 'D'] # the full list
indices = [0, 3] # the indices of myList that you want to extract
# Now build and join a new list comprehension using only those indices.
partList = "".join([e for i, e in enumerate(mylist) if i in indices])
print(partList) # >>> AD
As pointed out in the comments by DSM, if you're concerned with efficiency and you know your list of indices will be "friendly" (that is, it won't have any indices too big for the list you're cutting up), you can use a simpler expression without enumerate:
partList = "".join([mylist[i] for i in indices])

What you are intending to perform is not slicing but selecting.
The closest possibility, I can think of is to use operator.itemgetter
>>> from operator import itemgetter
>>> mylist = ['A', 'B', 'C', 'D']
>>> ''.join(itemgetter(0,3)(mylist))
'AD'
If you need to use a variable, then use a splat operator
index = (0,3)
''.join(itemgetter(*index)(mylist))

Related

restructure lists of lists by iteration in Python

I have a 2D list or list of lists.
Input file is
A 58.76-65.9
B 58.76-65.9
C 58.76-65.9
A 24.8-62.8
I then created a list of lists:
with open("Input.txt", "r") as file:
raw = [[str(x) for x in line.split()] for line in file]
print (raw)
which returns
[['A', '58.76-65.9'], ['B', '58.76-65.9'], ['C', '58.76-65.9'], ['A', '24.8-62.8']]
My aim is to now create a new list of lists with a new structure. How can I obtain a new list of lits like this?
[['58.76-65.9', 'A', 'B', 'C'], ['A', '24.8-62.8']]
I first tried unioning sets, but that creates one large list and I need lists of lists. Therefore my plan is to (1) Create a new empty list of lists,
(2) iterate through the original list of lists,
(3) check if the 2nd element (i.e. 58.76-65.9) exists in the new list lists of lists. If it does not, extend both elements. If it does, just the first element (ie A)
# Defining empty list
matches=[]
# Accesing each row in the 2d list
for r in raw:
if r[1] not in matches[0][]:
matches.append([r[1], r[0]])
I realize that matches[0][] is not correct, what is the correct way to access it?
Use the grouping idiom:
>>> data = [['A', '58.76-65.9'], ['B', '58.76-65.9'], ['C', '58.76-65.9'], ['A', '24.8-62.8']]
>>> from collections import defaultdict
>>> grouper = defaultdict(list)
>>> for x, y in data:
... grouper[y].append(x)
...
>>> grouper
defaultdict(<class 'list'>, {'24.8-62.8': ['A'], '58.76-65.9': ['A', 'B', 'C']})
Now, I honestly think the above data-structure is much more practical, but you can easily convert into a list-of-lists if you really want:
>>> [[k] + v for k, v in grouper.items()]
[['24.8-62.8', 'A'], ['58.76-65.9', 'A', 'B', 'C']]
Or even nicer:
>>> [[k, *v] for k, v in grouper.items()]
[['24.8-62.8', 'A'], ['58.76-65.9', 'A', 'B', 'C']]
Just use the dictionary data structure. It does, what you want:
# Load data:
my_array = [[1 , 10], [2, 10], [3, 20]]
# Result as a dictionary:
result = {}
# Loop over data:
for value, key in my_array:
if key not in result:
# Create new list
result[key]=[]
result[key].append(value)
# If you really need a list of lists as output, do something like:
result_l = [list(elem) for elem in result.items()]
# (in python3)

Is it possible to filter list of substrings by another list of strings in Python?

To filter list of strings by another list of strings in Python we can use the following code:
result = [x for x in strings1 if x in strings2]
But how can we filter list of substrings by another list of strings? For example:
substrings = ['a', 'b', 'c']
strings = ['_b_', '_c_', '_d_']
Result should be:
result = ['b', 'c']
You can use something like that:
[x for x in substrings if [y for y in strings if x in y]]
In [1]: substrings = ['a', 'b', 'c']
In [2]: strings = ['_b_', '_c_', '_d_']
In [3]: [x for x in substrings if [y for y in strings if x in y]]
Out[3]: ['b', 'c']
Elegant way to achieve this is via using any with a list comprehension as:
>>> substrings = ['a', 'b', 'c']
>>> my_strings = ['_b_', '_c_', '_d_']
>>> [s for s in substrings if any(s in i for i in my_strings)]
['b', 'c']
Here any will return True if any of string in substrings is present as substring in my_strings. As soon as it finds the match, it will short-circuit the iteration (without checking for other matches) and will return the result as True. Due to the short-circuiting property of any, it won't make the unnecessary iteration across the entire list, resulting in better performance.

An elegant way to slice a list given another list of ids to slice from

I am looking for an elegant way to slice a list l in python, given a list of ids l_ids.
For example, instead of writing
new_list = [l[i] for i in l_ids]
Write something like (Pseudo code):
new_list = l[*l_ids]
Is there a similar way to slice lists?
I have the feeling that someone have asked that already, but I couldn't find any reference for it.
Edit: It is OK to assume that all the list items are of the same type?
You can use operator.itemgetter(*items) like this:
from operator import itemgetter
getter = itemgetter(*lst_ids)
new_list = list(getter(lst))
Also, note that I renamed l variable to lst because it is less ambiguous and should be avoided.
You can implicitly cast the tuple to a list using Python 3 unpacking, as #JonClements commented:
*new_list, = getter(lst)
Finally, since Python 3.5, you can also use extended unpacking:
new_list = [*getter(lst)]
You could use itemgetter
from operator import itemgetter
l = ['a', 'b', 'c', 'd', 'e']
l_ids = [1, 2, 3]
list(itemgetter(*l_ids)(l))
['b', 'c', 'd']
I don't think importing anything is particularly elegant, or pythonic.
List comprehensions work, and I can't see a reason not to use them (or no good reason to import something to do the same thing):
>>> x = [3,5,7,0,1,4,2,6]
>>> y = ['a','b','c','d','e','f','g','h']
>>> nList = [y[i] for i in x]
>>> nList
['d', 'f', 'h', 'a', 'b', 'e', 'c', 'g']
The list comprehension is doing the following:
indexes = [3,5,7,0,1,4,2,6]
data = ['a','b','c','d','e','f','g','h']
nList = []
for index in indexes:
nList += [data[index]]
The comprehension looks pretty pythonic and elegant to me.
I would go with itemgetter but you could also map list.__getitem__:
l = ['a', 'b', 'c', 'd', 'e']
l_ids = [1, 2, 3]
new = list(map(l.__getitem__, l_ids))
If all the list elements are of the same type, it is possible to use numpy:
from numpy import *
new_list = array(l)[l_ids]

Print biggest len of several lists

I have several lists in one list and I want to compare the length of the lists and print the list with biggest number of len.
example:
somelist = [['a','b','c'],['a','b']]
the first list has a bigger len (3) than the second list (2), how do I print this in python?
Use the max() function with a generator expression:
max(len(l) for l in somelist)
This calculates the length for each sublist and returns the largest one.
If instead you wanted to extract the list with the longest length itself (so ['a', 'b', 'c'] rather than 3, use len as the key argument:
max(somelist, key=len)
Demo:
>>> somelist = [['a', 'b', 'c'], ['a', 'b']]
>>> max(len(l) for l in somelist)
3
>>> max(somelist, key=len)
['a', 'b', 'c']

Combining elements in list using python

Given input:
list = [['a']['a', 'c']['d']]
Expected Ouput:
mylist = a,c,d
Tried various possible ways, but the error recieved is TypeError: list indices must be integers not tuple.
Tried:
1.
k= []
list = [['a']['a', 'c']['d']]
#k=str(list)
for item in list:
k+=item
print k
2.
print zip(*list)
etc.
Also to strip the opening and closing parenthesis.
What you want is flattening a list.
>>> import itertools
>>> l
[['a'], ['a', 'c'], ['d']]
>>> res = list(itertools.chain.from_iterable(l))
>>> res
['a', 'a', 'c', 'd']
>>> set(res) #for uniqify, but doesn't preserve order
{'a', 'c', 'd'}
Edit: And your problem is, when defining a list, you should seperate values with a comma. So, not:
list = [['a']['a', 'c']['d']]
Use commas:
list = [['a'], ['a', 'c'], ['d']]
And also, using list as a variable is a bad idea, it conflicts with builtin list type.
And, if you want to use a for loop:
l = [['a'], ['a', 'c'], ['d']]
k = []
for sublist in l:
for item in sublist:
if item not in k: #if you want list to be unique.
k.append(item)
But using itertools.chain is better idea and more pythonic I think.
While utdemir's answer does the job efficiently, I think you should read this - start from "11.6. Recursion".
The first examples deals with a similar problem, so you'll see how to deal with these kinds of problems using the basic tools.

Categories

Resources