Using an index to get an item - python

I have a list in python ('A','B','C','D','E'), how do I get which item is under a particular index number?
Example:
Say it was given 0, it would return A.
Given 2, it would return C.
Given 4, it would return E.

What you show, ('A','B','C','D','E'), is not a list, it's a tuple (the round parentheses instead of square brackets show that). Nevertheless, whether it to index a list or a tuple (for getting one item at an index), in either case you append the index in square brackets.
So:
thetuple = ('A','B','C','D','E')
print thetuple[0]
prints A, and so forth.
Tuples (differently from lists) are immutable, so you couldn't assign to thetuple[0] etc (as you could assign to an indexing of a list). However you can definitely just access ("get") the item by indexing in either case.

values = ['A', 'B', 'C', 'D', 'E']
values[0] # returns 'A'
values[2] # returns 'C'
# etc.

You can use _ _getitem__(key) function.
>>> iterable = ('A', 'B', 'C', 'D', 'E')
>>> key = 4
>>> iterable.__getitem__(key)
'E'

Same as any other language, just pass index number of element that you want to retrieve.
#!/usr/bin/env python
x = [2,3,4,5,6,7]
print(x[5])

You can use pop():
x=[2,3,4,5,6,7]
print(x.pop(2))
output is 4

Related

Usage of key in max function and argument-less count method

list_x = ['A', 'B', 'B', 'E']
x = max(set(list_x), key=list_x.count)
Can anyone explain what's happening here? I know max() returns the max value and the set() would return set of the given list but what is , key=list_x.count there? (also, why there is no input for count method? ie. list_x.count("B") )
Note: I got this line from someone else's submission online.
max() goes through the given iterable and returns the largest item.
The key parameter (also used in list.sort(), min(), and other similar functions) can be passed a function that's used to get what key to sort on. Basically, this key function is called once for each item in the iterable and that value is used for sorting instead.
The list_x.count count method is a reference to list.count(). This returns how many times the item is in the list.
Another way to write what you have would be:
max(set(list_x), key=lambda item: list_x.count(item))
It's just that instead of passing a function/lambda that calls list_x.count() to key, the list_x.count function itself was passed.
set() is being used here because a set can only contain unique elements. Since you are getting the count for each element, it is faster to use a set so you are not calling list_x.count('B') multiple times.
This computes the element in list_x that is repeated the most. set(list_x) is used to compute the max over, and for each (unique, of course) element in the set, the count of that element in the list is computed (as in list_x.count('B'), for example).
So:
list_x = ['A', 'B', 'B', 'E']
x = max(set(list_x), key=list_x.count)
# x = 'B'
list_x = ['A', 'B', 'B', 'E', 'A', 'A']
x = max(set(list_x), key=list_x.count)
# x = 'A'

How do I define a function with an input array parameter

I want to create a function with one input array parameter and then return an array from 1st,4th and 6th element.
This is what I have came up with so far. So basically I want to print a,d,f
def something(paramOne):
result = [paramOne[1,4,6]]
return result
print(something(['a','b','c','d','e','f']))
Use list comprehension to pull out the elements you want.
def something(paramOne):
select_list = [1,4,6]
return [paramOne[i-1] for i in select_list]
print(something(['a','b','c','d','e','f']))
Output:
['a', 'd', 'f']
Issue: Index of any iterable should be an integer, you are giving a list
Fix: Going through the list and if the index(i+1 to make it 1 indexed) is in our list add it to the result
def something(paramOne):
# result = [paramOne[1,4,6]] >>> Index of any iterable should be an integer, you are giving a list
result = [v for i,v in enumerate(paramOne) if i+1 in [1,4,6]] # here i am going through the list and if the index(i+1 to make it 1 indexed) is in our list add it to the result
return result
print(something(['a','b','c','d','e','f']))
['a', 'd', 'f']

Elegant slicing in python list based on index

I was wondering what would be an efficient an elegant way of slicing a python list based on the index. In order to provide a minimal example:
temp = ['a','b','c','d']
index_needed=[0,2]
How can I slice the list without the loop?
expected output
output_list =['a','c']
I have a sense that there would be a way but haven't figured out any. Any suggestions?
First, note that indexing in Python begins at 0. So the indices you need will be [0, 2].
You can then use a list comprehension:
temp = ['a', 'b', 'c', 'd']
idx = [0, 2]
res = [temp[i] for i in idx] # ['a', 'c']
With built-ins, you may find map performs better:
res = map(temp.__getitem__, idx) # ['a', 'c']
Since you are using Python 2.7, this returns a list. For Python 3.x, you would need to pass the map object to list.
If you are looking to avoid a Python-level loop altogether, you may wish to use a 3rd party library such as NumPy:
import numpy as np
temp = np.array(['a', 'b', 'c', 'd'])
res = temp[idx]
# array(['a', 'c'],
# dtype='<U1')
res2 = np.delete(temp, idx)
# array(['b', 'd'],
# dtype='<U1')
This returns a NumPy array, which you can then be converted to a list via res.tolist().
Use this :
temp = ['a','b','c','d']
temp[0:4:2]
#Output
['a', 'c']
Here first value is starting index number which is (Included) second value is ending index number which is (Excluded) and third value is (steps) to be taken.
Happy Learning...:)
An alternative that pushes the work to the C layer on CPython (the reference interpreter):
from operator import itemgetter
temp = ['a','b','c','d']
index_needed=[0,2]
output_list = itemgetter(*index_needed)(temp)
That returns tuple of the values; if list is necessary, just wrap in the list constructor:
output_list = list(itemgetter(*index_needed)(temp))
Note that this only works properly if you need at least two indices; itemgetter is variable return type based on how it's initialized, returning the value directly when it's passed a single key to pull, and a tuple of values when passed more than one key.
It's also not particularly efficient for one-off uses. A more common use case would be if you had an iterable of sequences (typically tuples, but any sequence works), and don't care about them. For example, with an input list of:
allvalues = [(1, 2, 3, 4),
(5, 6, 7, 8)]
if you only wanted the values from index 1 and 3, you could write a loop like:
for _, x, _, y in allvalues:
where you unpack all the values but send the ones you don't care about to _ to indicate the lack of interest, or you can use itemgetter and map to strip them down to what you care about before the unpack:
from future_builtins import map # Because Py2's map is terrible; not needed on Py3
for x, y in map(itemgetter(1, 3), allvalues):
The itemgetter based approach doesn't care if you have more than four items in a given element of allvalues, while manual unpacking would always require exactly four; which is better is largely based on your use case.

How do I test if a list slice matches a set of values in any order?

For example, if I have a list like [a,b,c,d], and I needed to check if the elements at index 1,2 were b or c, then it would be true. For example, in [a,b,c,d], at index 1 there's a 'b' and at index 2 there's a 'c' which returns true. However, if the elements in those indexes were not a combination of b and c then false. So there has to be a 'b' or 'c' in index 1 and 2, cannot be (b and b) or (c and c). I'm not sure how to compare this.. Any hints?
[a,b,c,d] is True because elements in index 1 and 2 contain a combination of b or c
A general solution to this is to use set membership. So you could so:
s = set(vals[1:3])
if s == set(["b", "c"]):
...
This will create a set from vals[1] and vals[2], and check if that set contains exactly the elements "b" and "c".
You can use a Counter for this, assuming the types you're interested in are hashable.
from collections import Counter
def check_counts(l, compare_to):
return Counter(l) == Counter(compare_to)
l = ['a', 'b', 'c', 'd']
print(check_counts(l[1:3], ['c', 'b']))
This is similar to a solution using set, but allows for cases where you care about the number of a certain element
Given a list of items and a slice to match:
items = ['a', 'b', 'c', 'd']
match = ['b', 'c']
all you need is:
matches = items[1:3] in (match, match[::-1])
Note: match[::-1] returns a reversed version of match.
Alternative set-based version:
match = set(('b', 'c'))
# Version 1
matches = match.intersection(items[1:3]) == match
# Version 2
matches = not match.difference(items[1:3])

Remove list element without mutation

Assume you have a list
>>> m = ['a','b','c']
I'd like to make a new list n that has everything except for a given item in m (for example the item 'a'). However, when I use
>>> m.remove('a')
>>> m
m = ['b', 'c']
the original list is mutated (the value 'a' is removed from the original list). Is there a way to get a new list sans-'a' without mutating the original? So I mean that m should still be [ 'a', 'b', 'c' ], and I will get a new list, which has to be [ 'b', 'c' ].
I assume you mean that you want to create a new list without a given element, instead of changing the original list. One way is to use a list comprehension:
m = ['a', 'b', 'c']
n = [x for x in m if x != 'a']
n is now a copy of m, but without the 'a' element.
Another way would of course be to copy the list first
m = ['a', 'b', 'c']
n = m[:]
n.remove('a')
If removing a value by index, it is even simpler
n = m[:index] + m[index+1:]
There is a simple way to do that using built-in function :filter .
Here is ax example:
a = [1, 2, 3, 4]
b = filter(lambda x: x != 3, a)
If the order is unimportant, you can use set (besides, the removal seems to be fast in sets):
list(set(m) - set(['a']))
This will remove duplicate elements from your original list though
We can do it via built-in copy() function for list;
However, should assign a new name for the copy;
m = ['a','b','c']
m_copy=m.copy()
m_copy.remove('a')
print (m)
['a', 'b', 'c']
print(m_copy)
['b', 'c']
You can create a new list without the offending element with a list-comprehension. This will preserve the value of the original list.
l = ['a', 'b', 'c']
[s for s in l if s != 'a']
Another approach to list comprehension is numpy:
>>> import numpy
>>> a = [1, 2, 3, 4]
>>> list(numpy.remove(a, a.index(3)))
[1, 2, 4]
We can do it without using in built remove function and also without creating new list variable
Code:
# List m
m = ['a', 'b', 'c']
# Updated list m, without creating new list variable
m = [x for x in m if x != a]
print(m)
output
>>> ['b', 'c']
The question is useful as I sometimes have a list that I use throughout my given script but I need to at a certain step to apply a logic on a subset of the list elements. In that case I found it useful to use the same list but only exclude the needed element for that individual step, without the need to create a totally new list with a different name. For this you can use either:
list comprehension: say you have l=['a','b','c'] to exclude b, you can have [x for x in l if x!='b']
set [only if order is unimortant]: list(set(l) - set(['b'])), pay attention here that you pass 'b' as list ['b']

Categories