Python: Get item(s) at index list - python

I am trying to write something that takes a list, and gets the item(s) at an index, either one or multiple.
The example below which I found in another post here works great when I have more than one index. This example doesnt work if b = a single index.
a = [-2,1,5,3,8,5,6]
b = [1,2,5]
c = [ a[i] for i in b]
How do I get this to work with both 1 and multiple index?
Example:
a = [-2,1,5,3,8,5,6]
b = 2
c = [ a[i] for i in b] doesnt work in this case

You can actually check if the type your trying to use for fetching the indices is a list (or a tuple, etc.). Here it is, wrapped into a function:
def find_values(in_list, ind):
# ind is a list of numbers
if isinstance(ind, list):
return [in_list[i] for i in ind]
else:
# ind is a single numer
return [in_list[ind]]
in_list = [-2,1,5,3,8,5,6]
list_of_indices = [1,2,5]
one_index = 3
print(find_values(in_list, list_of_indices))
print(find_values(in_list, one_index))
The function takes the input list and the indices (renamed for clarity - it's best to avoid single letter names). The indices can either be a list or a single number. If isinstance determines your input is a list, it proceeds with a list comprehension. If it's a number - it just treats it as an index. If it is anything else, the program crashes.
This post gives you more details on isinstance and recognizing other iterables, like tuples, or lists and tuples together.

a = [-2, 1, 5, 3, 8, 5, 6]
a2 = [-2]
b = [1, 2, 5]
b2 = [1]
c = [a[i] for i in b]
c2 = [a2[i-1] for i in b2]
The first item of the list is 0, the list with one item is perfectly valid.

Instead of creating a list that manually validates the value of list b in the list a, you could create a separate 3 line code to print out the overlapping intersection of list a and b by this:
a = [-2,1,5,3,8,5,6]
b = [3,4,6]
for i in range(0,len(b)):
if b[i] in a:
print(b[i])
By doing so, you would be able to print out the overlapping intersection even if there were 1 or even no value stored in list b.

Related

Save list number within a list only if it contains elements in python

I have list of lists such as :
my_list_of_list=[['A','B','C','E'],['A','B','C','E','F'],['D','G','A'],['X','Z'],['D','M'],['B','G'],['X','Z']]
as you can see, the list 1 and 2 share the most elements (4). So, I keep a list within my_list_of_list only if the 4 shared elements (A,B,C or E) are present within that list.
Here I then save within the list_shared_number[], only the lists 1,2,3 and 6 since the other does not contain (A,B,C or E).
Expected output:
print(list_shared_number)
[0,1,2,5]
Probably sub optimal because I need to iterate 3 times over lists but it's the expect result:
from itertools import combinations
from functools import reduce
common_elements = [set(i).intersection(j)
for i, j in combinations(my_list_of_list, r=2)]
common_element = reduce(lambda i, j: i if len(i) >= len(j) else j, common_elements)
list_shared_number = [idx for idx, l in enumerate(my_list_of_list)
if common_element.intersection(l)]
print(list_shared_number)
# Output
[0, 1, 2, 5]
Alternative with 2 iterations:
common_element = {}
for i, j in combinations(my_list_of_list, r=2):
c = set(i).intersection(j)
common_element = c if len(c) > len(common_element) else common_element
list_shared_number = [idx for idx, l in enumerate(my_list_of_list)
if common_element.intersection(l)]
print(list_shared_number)
# Output
[0, 1, 2, 5]
You can find shared elements by using list comprehension. Checking if index 0 and index 1:
share = [x for x in my_list_of_list[0] if x in my_list_of_list[1]]
print(share)
Assume j is each item so [j for j in x if j in share] can find shared inner elements. if the length of this array is more than 0 so it should include in the output.
So final code is like this:
share = [x for x in my_list_of_list[0] if x in my_list_of_list[1]]
my_list = [i for i, x in enumerate(my_list_of_list) if len([j for j in x if j in share]) > 0]
print(my_list)
You can use itertools.combinations and set operations.
In the first line, you find the intersection that is the longest among pairs of lists. In the second line, you iterate over my_list_of_list to identify the lists that contain elements from the set you found in the first line.
from itertools import combinations
comparison = max(map(lambda x: (len(set(x[0]).intersection(x[1])), set(x[0]).intersection(x[1])), combinations(my_list_of_list, 2)))[1]
out = [i for i, lst in enumerate(my_list_of_list) if comparison - set(lst) != comparison]
Output:
[0, 1, 2, 5]
Oh boy, so mine is a bit messy, however I did not use any imports AND I included the initial "finding" of the two lists which have the most in common with one another. This can easily be optimised but it does do exactly what you wanted.
my_list_of_list=[['A','B','C','E'],['A','B','C','E','F'],['D','G','A'],['X','Z'],['D','M'],['B','G'],['X','Z']]
my_list_of_list = list(map(set,my_list_of_list))
mostIntersects = [0, (None,)]
for i, IndSet in enumerate(my_list_of_list):
for j in range(i+1,len(my_list_of_list)):
intersects = len(IndSet.intersection(my_list_of_list[j]))
if intersects > mostIntersects[0]: mostIntersects = [intersects, (i,j)]
FinalIntersection = set(my_list_of_list[mostIntersects[1][0]]).intersection(my_list_of_list[mostIntersects[1][1]])
skipIndexes = set(mostIntersects[1])
for i,sub_list in enumerate(my_list_of_list):
[skipIndexes.add(i) for char in sub_list
if i not in skipIndexes and char in FinalIntersection]
print(*map(list,(mostIntersects, FinalIntersection, skipIndexes)), sep = '\n')
The print provides this :
[4, (0, 1)]
['E', 'C', 'B', 'A']
[0, 1, 2, 5]
This works by first converting the lists to sets using the map function (it has to be turned back into a list so i can use len and iterate properly) I then intersect each list with the others in the list of lists and count how many elements are in each. Each time i find one with a larger number, i set mostIntersections equal to the len and the set indexes. Once i go through them all, i get the lists at the two indexes (0 and 1 in this case) and intersect them to give a list of elements [A,B,C,E] (var:finalIntersection). From there, i just iterate over all lists which are not already being used and just check if any of the elements are found in finalIntersection. If one is, the index of the list is appended to skipIndexes. This results in the final list of indexes {indices? idk} that you were after. Technically the result is a set, but to convert it back you can just use list({0,1,2,5}) which will give you the value you were after.

Filtering a list of two-element sublists with a list comprehension

I have a list of lists
input = [[2,13],[5,3],[10,8],[13,4],[15,0],[17,10],[20,5],[25,9],[28,7],[31,0]]
I want to write a list comprehension where for the [a,b] pairs above I get the pairs where b > a. In the above example that would be [2,13].
My attempt
x = [[item[i],[j]] for item in inputArray if j>i]
produces a NameError
NameError: name 'j' is not defined`
The problem with your attempt is that you never tell Python what i and j are supposed to be. The check j > i cannot be computed and the list [item[i],[j]] can't be built without that information.
You can issue
>>> inp = [[2,13],[5,3],[10,8],[13,4],[15,0],[17,10],[20,5],[25,9],[28,7],[31,0]]
>>> [[a, b] for a, b in inp if b > a]
[[2, 13]]
This solution does not produce a NameError because for a, b in inp tells Python to iterate over the elements of inp (two-element sublists) and in each iteration assign the name a to the first element of a sublist and the name b to the second element.
I used the name inp instead of input because the latter is already taken by a builtin function for getting user input.
Explanation of the list comprehension
The comprehension is equivalent to
>>> result = []
>>> for a, b in inp:
... if b > a:
... result.append([a, b])
...
>>> result
[[2, 13]]
Every two-element list in inp is unpacked into the variables a and b. If the filter condition b > a is True, then a list [a, b] is built and included in the final result.
If you don't want to use unpacking, you can also index into the sublists of inp like this:
>>> [sub[:] for sub in inp if sub[1] > sub[0]]
[[2, 13]]
Taking a full slice of sub via sub[:] ensures that like in the other solutions presented so far, the filtered result stores (shallow) copies of the sublists of inp. If copying it not necessary, you can omit the [:].
This code does not produce a NameError because for sub in inp tells Python to iterate over inp and in each iteration assign the name sub to the next sublist. In addition, explicit numbers (0 and 1) are used for the indices.
Personally, I prefer the solution with unpacking. It is easier to read and will run even if the elements of inp don't support indexing, but are iterables from which two elements can be extracted.
You should unpack each pair into the i, j variables, and then you can compare them:
x = [[i, j] for i,j in inputList if j > i]
(note I have renamed inputArray, inputList)
Or without unpacking:
x = [item for item in inputList if item[1] > item[0]]

Simultaneously iterate over multiple list and capture difference in values

Consider API returning four lists as output. Let's consider output as
a = [1,2,3,4]
b = [1,2,3,4]
c = [1,2,4,3]
d = [1,2,3,5]
Now, first we want to compare these lists are equal or not.
Lists are equal only if elements and there indexes matches.
For example, from above lists, a and b are equal. But a and c are not equal.
If the lists are not equal, then output is expected as: this element at this index in this list is not same as other.
For comparing and getting differences of two lists, I have written below code.
for i in range(len(a)):
if a[i] != c[i]:
print "Expected value at ",i," is ",a[i]
print "But got value ",c[i],"in second list"
Now question is how to achieve this for all four above lists?
You may use zip to iterate over each list simultaneously and compare the value at each index. In the below example, I am comparing the value of list a with remaining lists.
a = [1,2,3,4]
b = [1,2,3,4]
c = [1,2,4,3]
d = [1,2,3,5]
for i, x in enumerate(zip(a, b, c, d)):
print('--------- Index: {}'.format(i))
base = x[0]
for j, y in enumerate(x[1:], 2):
if base!=y:
print('{} not equal to {} : --> List {}'.format(base, y, j))
which prints:
--------- Index: 0
--------- Index: 1
--------- Index: 2
3 not equal to 4 : --> List 3
--------- Index: 3
4 not equal to 3 : --> List 3
4 not equal to 5 : --> List 4
From the comment:
How to find in which list we have different value?
import collections as ct
counter = ct.Counter(map(tuple, [a,b,c,d])) # make hashable keys w/tuples
base = counter.most_common(1)[0][0] # find most frequent sequence
[list(seq) for seq in counter if seq != base] # filter uncommon sequences
Output (the non-matching lists):
[[1, 2, 4, 3], [1, 2, 3, 5]]
We collect all similar sequences as keys in a collections.Counter. If all sequences match, there should only be one entry in the Counter dictionary. Otherwise, filter the remaining sequences.
Set up a list mylist = [a, b, c,d] Then loop through checking which ones are equal and which ones are not equal.
for i in range(len(mylist)-1)
for j in range(i+1, len(mylist))
# Check mylist[i] agaist mylist[j] and report results
For example, this will test a against b, c, and d
b against c and d
c against d

Compare with each other, items inside two lists, in a for loop?

How do I check in Python, if an item of a list is repetead in another list?
I suppose that I should use a FOR loop, to go and check item by item, but I´m stuck in something like this (which I know it´s not correct):
def check(a, b):
for item in b:
for item1 in a:
if b[item] in a[item1]:
b.remove(b[item1])
I want to remove repeated elements in the second list in comparision with the first list.
Edit: I do assume that list a has items that are repeated in list b. Those items can be of any type.
Desired output:
a=[a,b,c]
b=[c,d,e]
I want to append both lists and print: a b c d e
Assuming that a and b do not contain duplicate items that need to be preserved and the items are all hashable, you can use Python has a built in set:
c = list(set(b) - set(a))
# c is now a list of everything in b that is not in a
This would work for:
a, b = range(7), range(5, 11)
but it would not work for:
a = [1, 2, 1, 1, 3, 4, 2]
b = [1, 3, 4]
# After the set operations c would be [2]
# rather than the possibly desired [2, 2]
In the case when duplicates are desired you can do the following:
set_b = set(b)
c = [x for x in a if x not in b]
Using a set for b will make the lookups O(1) rather than O(N) (which will not matter for small lists).
You can use Python's set operations without the need for loops:
>>> a = [1,2]
>>> b = [2]
>>> set(a) - set(b)
set([1])
>>>
Use the set command and list to get the list back.
d = list(set(a + b))
You can use list.sort() if you want to sort the list as well.

How to remove the first and last item in a list?

I have the List
['Q 0006 005C 0078 0030 0030 0033 0034 ONE_OF 0002 ']
How do I remove the first element, Q and 0002, the last element?
If your list is stored under my_list then this should work.
my_list = my_list[1:-1]
I'm not sure exactly what you want since it is unclear but this should help. You actually only have a single element in that list.
Assuming all your list items are strings with spaces as delimiters, here is how you can remove the first and last group of characters from each string in the list.
>>> L = ['Q 0006 005C 0078 0030 0030 0033 0034 ONE_OF 0002 ']
>>> [' '.join(el.split()[1:-1]) for el in L]
['0006 005C 0078 0030 0030 0033 0034 ONE_OF']
Another (quite Pythonic) way to do it is using the extended sequence unpacking feature:
my_list = _ , *my_list, _
Example
>>> my_list = [1, 2, 3, 4, 5]
>>> _, *my_list, _ = my_list
>>> my_list
[2, 3, 4]
Another question was redirected here, asking what this line does, given that res is a list:
c, *res, c = res
This uses multiple assignment and extended iterable unpacking. In Python you can do something like this:
a, b, c = 1, 2, 3
To assign 1 to a, etc. - this is multiple assignment, assigning multiple values in a single assignment statement.
If the right side consists of an iterable, Python will 'unpack' the iterable to assign the parts. For example:
t = (1, 2, 3) # a tuple
a, b, c = t # after this, a == 1, b == 2, c == 3
However, in the given example (with c and res), the iterable on the right doesn't have to have the same number of items as the number of targets on the left.
This is where "extended iterable unpacking" comes in. For the documentation: "allowing to specify a “catch-all” name which will be assigned a list of all items not assigned to a “regular” name."
So, in c, *res, c = res, the first element of res is assigned to c, the last element is assigned to c, but everything else from the unpacked iterable (the list in this case) is assigned to *res, which will make res a list again.
Note the following:
res = (1, 2, 3, 4)
c, *res, c = res
Here, you may expect res to end up as (2, 3) - but that's not the case, after running, res will be [2, 3], a list. The assignment does not transfer the type, only the values. And the extended iterable unpacking results in res being a list after the assignment, even though the values came from a tuple.
Finally, note that nicer syntax might be:
res = [1, 2, 3, 4]
_, *res, _ = res
The use of _ makes it clear that these values are to be discarded. And it removes questions about what the value of c will be after c, *res, c = res. It's 4, because the assignments are evaluated left to right, but it's better to be clear.
#initialize 2 lists what will hold your integers
List1 = []
List2 = []
# prompt the user to enter the integers in the list
List1 = eval(input("Enter the list of integers:")
#Iterate over the list to remove the first and last integer
for i in range(len(List1):
List2 = list1[1:-1]
#print the contents of your new list to verify the results
print(List2) # the output shouldn't contain first and last integer of List1
# prompt the user to enter the integers in the list
List1 = eval(input("Enter the list of integers:")
#Iterate over the list to remove the first and last integer
for i in range(len(List1):
List2 = list1[1:-1]
#print the contents of your new list to verify the results
print(List2) # the output shouldn't contain first and last integer of List1

Categories