Counting string list in lists - python

I have two lists:
bigList = [["A1.1", "A2.1", "A3.1", "A4.1"], ["A3.1", "A4.1", "A5.1"], ["A4.1", "A5.1"]]
smallList = ["A4.1", "A5.1"]
What is the fastest way in Python to count how many times bigList (lists) contain smallList.
At the moment, the right answer is 2.
Maybe I should use Numpy array?

You can use set method issubset:
Syntax:
A.issubset(B)
Return Value from issubset()
The issubset() returns
True if A is a subset of B
False if A is not a subset of B
bigList = [["A1.1", "A2.1", "A3.1", "A4.1"], ["A3.1", "A4.1", "A5.1"], ["A4.1", "A5.1"]]
smallList = ["A4.1", "A5.1"]
count={}
track=1
for sub_list in bigList:
if set(smallList).issubset(sub_list):
if tuple(smallList) not in count:
count[tuple(smallList)]=track
else:
count[tuple(smallList)]+=1
print(count)
output:
{('A4.1', 'A5.1'): 2}

To check if a list contains another list entirely, we can use a set comparison:
set(smallerList) <= set(biggerList)
This returns True if all elements of smallerList are contained in the set of biggerList. Do note that this method checks if the individual items are contained and not the order - which sets do not regard. As such it cannot be used if the sequence order matters.
From here we can use a simple list comprehension to check through all the sets of bigList and apply the above check. Then we just sum up the number of sets that did contain the smaller set (aka we add 1 if it is a match, 0 if not).
count = sum([1 if set(smallList) <= set(bigList) else 0 for x in bigList])
As pointed out by N. Ivanov - this will scale linearly depending on how many sublists are contained in bigList.

Related

Detect where elements of two lists differ from one another according to their index

given these two lists
l1=[0,0,0,0,1,1,1,1]
l2=[0,0,0,1,1,1,1,1]
they are identical except for the 4th element. I need a code that detects the difference between these two sets and prints out the location of the detected difference. In this case it would be = 4.
The intersection and union command wouldn't work as they don't take the index into consideration.
I have tried this code, but it does not print out anything:
l1=[0,0,0,0,1,1,1,1]
l2=[0,0,0,1,1,1,1,1]
for i in l1:
if i != l2[l1.index(i)]:
print(l1.index(i),i)
Your code does not work because list.index(value [, pos]) only reports the first occurence of a value in that list [after pos].
This would report the differences:
l1=[0,0,0,0,1,1,1,1]
l2=[0,0,0,1,1,1,1,1]
print(*(p for p,v in enumerate(zip(l1,l2)) if v[0]^v[1]))
Output:
3
The zip(..) pairs up values positionally in to tuples, enumerate(..) gets the index, tuple value and v[0]^v[1] is a logical xor that is only true if the values differ at least in 1 bit.
See:
enumerate
zip
binary bitwise ops (including xor)
The simpler version of this works without zip:
for index,number in enumerate(l1): # get index & number of one list
if l2[index] != number: # compare to other number
print(f"On {index}: {number} != {l2[index]}")
You can use zip
l1=[0,0,0,0,1,1,1,1]
l2=[0,0,0,1,1,1,1,1]
diff_idx = [idx for idx,(x,y) in enumerate(zip(l1,l2)) if x != y]
print(diff_idx)
output
[3]
l1=[0,0,0,0,1,1,1,1]
l2=[0,0,0,1,1,1,1,1]
print(l1.index(l1 != l2))
The third line returns the index position of l1 which does not satisfy the condition l1 not equal to l2.

How to create list and initialize only some of it's values in Python (in comparison to C++)

I need to create an List of size N and then initialize only N-1th and N-2th elements only. Which means if the size of the list is 5 then it should only contain elements in 3rd and 4th position.
i know how to do it in C++ but is there any way to implement it in Python?
for example: In C++
int *n = new int[5];
n[3] = 20
n[4] = 10
//and if we print the output it will show some garbage values in index 0, 1, 2 and will print 20 10 which is the values we initailized
How can i do it in python? or anything similar to this!
In python, list must be initialized with values.
Closest thing you can do:
N = 5
lst = [0] * (N-2) + [20, 10]
This:
Fills the N-2 elements of a list with default value 0
Sets the value for the last two elements
Concatenates the zeros and last two elements sub-lists of stages 1 & 2
In python,
array=[]
length=5
for i in range(length):
array.append(0)
array[3]=20
array[4]=10
Edit: As pointed out by kabanus, a more efficient way to do this would be-
array=[0]*length
Instead of the for loop.

Grouping of elements of set with first n Natural numbers, excluding one arbitrary element, to give us a Sum equal to S

Array with elements sorted in descending order - l
ans=[]
for t in l:
if t<=S:
S-=t
ans.append(t)
if S==0:
break
ans, Gives us list with selected elements.
Please tell me whether it is satisfiable by all big numbers or not?
No it doesn't work for all cases:
For example: S = 17 and l = [10,5,4,3]
The answer and will be:
ans = [10,5] and
S = 2 (because it didn't get down to 0)
But it could have been solved by: ans [10,4,3]
For n=8 and omitted element=2.
This won't return the right answer.

Surprising order in python set combination methods

I am aware that set() in python doesn't have an order as it is implemented as a hash table. However, I was a little surprised to solve a question which involved order using set.intersection().
So I am given two lists with an order, say for example, denoting some ranking or sequence of occurrence. I have to find the element that is common to both lists and has highest order (occurs the first) in the two lists. For example,
List1 = ['j','s','l','p','t']
List2 = ['b','d','q','s','y','j']
should output 's' as it is the second best in List1 and occurs the first in List2.
If you convert each of the lists into sets and take an intersection Set1.intersection(Set2), you get a set set(['s', 'j']). In my case I could convert this into a list and spit out the first element and this was approximately O(n1 + n2).
I was happy to solve this interview question (all test passed), but I am amazed how could I pull off such a order based problem using python set.
Does anyone have a clue how this is working? What's a possible case, that this could breakdown?
EDIT: This seems to be like a stoke of luck case, so if you have a good solution for this problem, it will be also appreciated
I found a O(n1+n2) approach. Commented code follows. The trick is to create a lookup table (not a dictionary, a simple array) to index the minimum position of the letters in both lists, and then find the minimum of the sum of those positions and the associated letter.
List1 = ['j','s','l','p','t']
List2 = ['b','d','q','s','y','j']
# unreachable max value to initialize the slots
maxlen = max(len(List1),len(List2))+1000
# create empty slot_array (initialized to values higher than last letter pos
# for both lists (the value is greater than any "valid" position)
# first pos (index 0) is for letter "a", last pos is for letter "z"
slot_array = [[maxlen,maxlen] for x in range(ord('a'),ord('z')+1)]
# scan both lists, and update the position if lower than the one in slot_array
for list_index,the_list in enumerate((List1,List2)):
print(list_index)
for letter_index,letter in enumerate(the_list):
slot = slot_array[ord(letter)-ord('a')]
if slot[list_index]>letter_index:
slot[list_index] = letter_index
# now compute minimum of sum of both minimum positions for each letter
min_value = maxlen*2
for i,(a,b) in enumerate(slot_array):
sab = a+b
if sab < min_value:
min_value = sab
min_index = i
# result is the letter with the minimal sum
print(chr(min_index+ord('a')))
A list comprehension could do the job:
Set2 = set(List2)
[x for x in List1 if x in Set2]
This will maintain the order of List1, you could do the same for List2 too.
You can then call next on the list comprehension (or a generator to be more efficient) to get the first match.

Manually sort a list of 10 integers in python

I'm fairly new to programming; I've only been studying Python for a few weeks. I've been given an exercise recently that asks me to generate a list of integers, and then manually sort the numbers from lowest to highest in a separate list.
import random
unordered = list(range(10))
ordered = []
lowest = 0
i = 0
random.shuffle(unordered)
lowest = unordered[0]
while i in unordered:
if unordered[i] < lowest:
lowest = unordered[i]
i += 1
if i >= len(unordered):
i = 0
ordered.append(lowest)
unordered.remove(lowest)
lowest = unordered[i]
print(ordered)
This is what I have so far, and to be quite frank, it doesn't work at all. The pseudocode I have been given is this:
Create an empty list to hold the ordered elements
While there are still elements in the unordered list
Set a variable, lowest, to the first element in the unordered list
For each element in the unordered list
If the element is lower than lowest
Assign the value of that element to lowest
Append lowest to the ordered list
Remove lowest from the unordered list
Print out the ordered list
The biggest issue I'm having so far is that my counter doesn't reliably give me a way to pick out the lowest number from my list unordered. And then I'm having issues with indexing my list i.e. the index being out of range. Can anyone give me a bit of feedback on where I'm going wrong?
Also, I was given this info which I'm not really sure about:
You can use an established method to sort the list called the Selection Sort.
I'm not supposed to be using Python's built in sort methods this time around. It's all supposed to be done manually. Thanks for any help!
You can do this without having to create another list.
x = [5, 4, 3, 2, 5, 1]
n = len(x)
# Traverse through all list elements
for i in range(n):
# Traverse the list from 0 to n-i-1
# (The last element will already be in place after first pass, so no need to re-check)
for j in range(0, n-i-1):
# Swap if current element is greater than next
if x[j] > x[j+1]:
x[j], x[j+1] = x[j+1], x[j]
print(x)
This works with duplicates and descending lists. It also includes a minor optimization to avoid an unnecessary comparison on the last element.
Note: this answer and all the others use bubble sort, which is simple but inefficient. If you're looking for performance, you're much better off with another sorting algorithm. See which is best sorting algorithm and why?
You've just got some of the order wrong: you need to append to your ordered list each time around
import random
unordered = list(range(10))
ordered = []
i = 0
random.shuffle(unordered)
print unordered
lowest = unordered[0]
while len(unordered) > 0:
if unordered[i] < lowest:
lowest = unordered[i]
i += 1
if i == len(unordered):
ordered.append(lowest)
unordered.remove(lowest)
if unordered:
lowest = unordered[0]
i = 0
print(ordered)
you're not supposed to create a new algorithm for sorting list, just implement this one :
http://en.wikipedia.org/wiki/Bubble_sort
I found this is working pretty well for any number of inputs
x = [3, 4, 100, 34, 45]
for i in range(len(x) - 1):
if x[i] > x[i + 1]:
x[i],x[i + 1] = x[i + 1], x[i]
print (x)
Above code won't work if you have repetitive elements.
ordered=[]
i=0
j=0
x = [100, 3, 4, 100, 34, 45]
lowest=x[0]
while len(x)>0:
for i in range(0,len(x)):
if x[i]<=lowest:
lowest=x[i]
ordered.append(lowest)
x.remove(lowest)
if len(x)>1:
lowest=x[0]
print(ordered)
def sort(x):
l=len(x)
for i in range(l):
for j in range((i+1),l):
if x[i]>x[j]:
l1=x[i]
x[i]=x[j]
x[j]=l1
print(x)
l=[8,4,2,6,5,1,12,18,78,45]
sort(l)
From the first number in the list, run a loop to find the lowest value. After that swap them with the first number in the list. Repeat this loop method for remaining numbers in the list.
nlist=[int(a) for a in input('Please insert your list of numbers ').split()]
for loop1 in range (0,len(nlist)-1): # outer loop
min=nlist[loop1]
for loop2 in range (loop1 + 1,len(nlist)): # inner loop to compare
if min > nlist[loop2]:
min=nlist[loop2]
index=loop2
if nlist[loop1] != min:
swap=nlist[loop1]
nlist[loop1]=min
nlist[index]=swap
print('Your hand-sorted list is',nlist)

Categories

Resources