find out entries not present in a list - python

I have a list of list of node names and I have a graph with total nodes.
I need to find out nodes names which is not present in list of nodes names.
Ex:
list of lists of nodes names: [[x,y,h,j,k],[a,b,c],[t,q,r,v,x,y,k],[a,h,y,q,c]]
graph : all the node names ( need to iterate and find the node names)
E.g. (node names): [a,b,c,x,y,h,j,k,t,q,r,v]
For the first list [x,y,h,j,k] in loop,
need to return the list of remaining node names present in the graph: [a,b,c,t,q,r,v]
It should run in loop for each list inside list of node names.
I am using python and networkx. Please help me out

I would suggest using sets or dicts for efficiency.
lists_of_nodes = [['x','y','h','j','k'],['a','b','c'],['t','q','r','v','x','y','k'],['a','h','y','q','c']]
sets_of_nodes = map(set, lists_of_nodes)
all_nodes = reduce(lambda l, r: l.union(r), sets_of_nodes)
complements = [list(all_nodes.difference(node_set)) for node_set in sets_of_nodes]
for complement in complements:
print complement
'''
['a', 'c', 'b', 'q', 'r', 't', 'v']
['h', 'k', 'j', 'q', 'r', 't', 'v', 'y', 'x']
['a', 'h', 'c', 'b', 'j']
['b', 'k', 'j', 'r', 't', 'v', 'x']
'''

l = [['x','y','h','j','k'],['a','b','c'],['t','q','r','v','x','y','k'],['a','h','y','q','c']]
def return_remaining(list_of_nodes):
total = ['a','b','c','x','y','h','j','k','t','q','r','v']
for node in list_of_nodes:
if node in total:
total.remove(node)
return total
for i in range(len(l)):
print return_remaining(l[i])
Output
['a', 'b', 'c', 't', 'q', 'r', 'v']
['x', 'y', 'h', 'j', 'k', 't', 'q', 'r', 'v']
['a', 'b', 'c', 'h', 'j']
['b', 'x', 'j', 'k', 't', 'r', 'v']

Related

To find commonality/characteristics of in a group of lists

A group of lists of equal length (strings as elements). I want to find out their commonality/characteristics.
Let’s call them “good” lists - I want to find out what makes a “good” list.
A thinking is to output all 3-element combination from each list, then summarize the occurrences of the 3-element to rank them.
For example, “D” and “N” and “T” appeared 4 times. It may conclude that, when “D” and “N” and “T” appear in a list, it is a “good” list.
The same method can apply to 4-element combinations, 5-element combinations (when the many lists are very long).
What would be a better solution?
import itertools
from itertools import combinations
from collections import Counter
s = [
['O', 'V', 'R', 'M', 'Y'],
['I', 'Q', 'L', 'J', 'A'],
['M', 'I', 'Q', 'N', 'G'],
['Y', 'M', 'R', 'Q', 'Z'],
['D', 'X', 'C', 'Q', 'N'],
['B', 'O', 'Q', 'E', 'V'],
['V', 'M', 'J', 'G', 'R'],
['M', 'T', 'L', 'I', 'Z'],
['Y', 'H', 'A', 'V', 'L'],
['O', 'T', 'D', 'N', 'E'],
['D', 'N', 'T', 'I', 'G'],
['T', 'Q', 'H', 'I', 'P'],
['F', 'T', 'D', 'W', 'N'],
['F', 'Z', 'H', 'E', 'X'],
['E', 'Z', 'R', 'K', 'J'],
['P', 'C', 'U', 'D', 'F'],
['N', 'I', 'Y', 'U', 'E'],
['T', 'N', 'D', 'L', 'V'],
['D', 'Z', 'I', 'P', 'X'],
['H', 'L', 'C', 'P', 'Y']]
summary = []
for each in s:
all_combinations = [comb for comb in combinations(each, 3)] # unique combinations only
for a in all_combinations:
summary.append('-'.join(sorted(a)))
print (Counter(summary))
Output:
Counter({'D-N-T': 4, 'M-R-V': 2, 'M-R-Y': 2.....})
I think I would make use of an sql database to do this (sqlite in the examples below). You could create a table with two columns element and list (both primary keys). You would populate it with the elements from all lists like this:
element | list
-----------------
O 1
V 1
R 1
M 1
Y 1
I 2
Q 2
L 2
J 2
A 2
...
You could run a query like the following to figure out which elements appear how many times in the lists:
SELECT element, count(element) as cnt FROM table, (SELECT distinct(element) as dst from table) as table2
WHERE element = table2.dst
GROUP BY element
ORDER BY cnt DESC
You can also run a query to find all lists that contain your elements of choice. Here is the query to find all lists that contain D, N and T:
SELECT COUNT(element), list FROM table WHERE element IN ('D', 'N', 'T')
GROUP BY list
HAVING COUNT(element) = 3;

How to print the slice of the list of words that only includes letters. python? But what am i missing?

This is what I have so far:
strVar = 'Together We Thrive, Class of 2025!'
def stringToList(string):
listRes = list(string.split(" "))
return listRes
strVar = 'Together We Thrive, Class of 2025!'
strVarList = print(stringToList(strVar))
I know I need to have append and sort somewhere in there.
These are the instructions:
Convert the provided string to a list using a for loop or built-in function and store the result in a new variable.
Sort the list.
Print the slice of the list that only includes letters.
This what my answer I supposed to look like:
['C', 'T', 'T', 'W', 'a', 'e', 'e', 'e', 'e', 'f', 'g', 'h', 'h', 'i', 'l', 'o', 'o', 'r', 'r', 's', 's', 't', 'v']
Kindly try:
sorted([x for x in 'Together We Thrive, Class of 2025!' if x.isalpha()])
Or, pass the name of the defined variable.
This outputs:
['C',
'T',
'T',
'W',
'a',
'e',
'e',
'e',
'e',
'f',
'g',
'h',
'h',
'i',
'l',
'o',
'o',
'r',
'r',
's',
's',
't',
'v']
please try this:
strvar = "Together we Thrive, Class of 2025!"
Listt=[ ]
for letter in strvar:
if (letter.isalpha()):
Listt.append(letter)
Listt.sort()
print(Listt)

How do you remove a list element

I am trying to make a small program that will jumble up the letters of the alphabet(In simple terms)
I have tried to use things like list.pop() or list.remove(), But those did nothing
import random
def rand_let():
i = 26
alphabet = str('')
for a in range(1, 26):
key = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
print(len(key))
print(key)
letter = random.randint(1, i)
print(key[letter])
letters = key[letter]
alphabet += str(letters)
key.remove(letter)
i -= 1
rand_let()
I want it to jumble up the alphabet,
it is, but the way it is doing it will make letters repeat(I don't want it to repeat)
The shuffle function from random will save you many lines, and does what you're looking for:
import random
alphabet = ['A', 'B', 'C']
random.shuffle(alphabet)
print(alphabet)
#Ex: ['C', 'A', 'B']
The reason you are getting duplicates is that although you have code to remove the letter from the key list, the line that declares the key list is within the loop as well. Try moving the line
key = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
above the for loop. Or, as suggested in other answers, use a library to do this for you.
import random
import string
alphabet = [letter for letter in string.ascii_uppercase]
random.shuffle(alphabet)
print(alphabet)
This will just shuffle the list and then print the elements of the list one by one for each iteration of the for loop.
import random
key = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
random.shuffle(key)
def choice(x):
for letter in key:
print()
choice(key)

produce a random subset of all permutations

I'm looking for a way to randomly sample a fixed length subset of all permutations.
import itertools
from random import shuffle
mylist = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T']
APPROACH A
Approach A below suffers from the problem that the permutations are too similar.
a_pre = itertools.permutations(mylist,20)
a = itertools.islice(a_pre,3)
list(a)
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T']
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'T', 'S']
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'S', 'R', 'T']
APPROACH B
Approach B gets me closer to my desired outcome, but here there's always a risk of producing identical ordering between lists, so this approach is not feasible.
#repeat n=3 times
shuffle(mylist)
print(mylist)
['J', 'B', 'M', 'A', 'O', 'C', 'K', 'S', 'H', 'Q', 'N', 'T', 'R', 'D', 'G', 'P', 'I', 'E', 'F', 'L']
['R', 'O', 'C', 'I', 'G', 'E', 'Q', 'L', 'P', 'J', 'F', 'N', 'A', 'B', 'H', 'T', 'D', 'K', 'M', 'S']
['L', 'O', 'I', 'G', 'B', 'E', 'R', 'A', 'D', 'N', 'J', 'S', 'H', 'F', 'K', 'M', 'Q', 'T', 'C', 'P']
but here there's always a risk of producing identical ordering between lists, so this approach is not feasible.
You can use tuples (since lists aren't hashable) and sets (so that there are no duplicates/identical lists) to get around this:
from random import shuffle
mylist = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T']
myset = set()
while len(myset) < 5: #change 5 to however many you want
shuffle(mylist)
myset.add(tuple(mylist))
print([list(x) for x in myset])
Edit: As #tobias_k points out:
For the given list, there are 20! = 2432902008176640000 different permutations, so collisions are really very unlikely.
Consider the itertools random_permutation recipe:
From the docs:
def random_permutation(iterable, r=None):
"Random selection from itertools.permutations(iterable, r)"
pool = tuple(iterable)
r = len(pool) if r is None else r
return tuple(random.sample(pool, r))
Code
import string
import more_itertools as mit
iterable = string.ascii_uppercase[:-6]
[random_permutation(iterable) for _ in range(3)]
Output
[('M', 'K', 'Q', 'A', 'I', 'J', 'H', 'T', 'C', 'E', 'P', 'L', 'B', 'N', 'G', 'F', 'S', 'D', 'O', 'R'),
('A', 'G', 'I', 'S', 'E', 'T', 'B', 'Q', 'D', 'M', 'C', 'O', 'J', 'H', 'N', 'F', 'K', 'P', 'R', 'L'),
('C', 'S', 'O', 'H', 'I', 'K', 'A', 'G', 'D', 'B', 'R', 'E', 'L', 'T', 'M', 'N', 'F', 'P', 'Q', 'J')]
more_itertools is a third-party library that implements this recipe for you.
you could use this to generate the number-th lexicographic perutation of N elements:
def permutation_from_int(N, number):
'''
get the number-th lexicographic permutation of length N.
N: the length of the permutation
0 <= number <= factorial(N) -1: the number of the desired
permutation
'''
# assert 0 <= number < factorial(N)
ret = [None] * N
select = list(range(N))
for i in range(N - 1, -1, -1):
index, number = divmod(number, factorial(i))
element = select[index]
ret[N - 1 - i] = element
select.remove(element)
return ret
then you just have to generate (and keep a set of - if you want to avoid duplicates) random integers that represent the permutations:
N_TESTS = 17
strg = 'ABCD'
N = len(strg)
N_MAX = factorial(N)
seen = set()
for _ in range(N_TESTS):
number = randrange(N_MAX)
while number in seen:
number = randrange(N_MAX)
seen.add(number)
perm = permutation_from_int(N, number)
print(''.join(strg[i] for i in perm))
note that this may loop forever if the number of test is bigger that the space of all the permutations...
which prints (e.g.):
DACB
DBCA
BADC
BDCA
DCAB
DABC
CADB
DBAC
DCBA
...
but as mentioned in the other answers: if you have a permutation of 20 elements the chance of hitting a repeated permutation is very small!
I think your question is a special case of one I had, for k=N
Based on this, the two solutions stated there should apply. The first one is a tad slow :)
So the random sampling one (Which you also hint at your question, just discard duplicates...) seems to be the only answer for now.
It would be very interesting to see if there is a generative solution to either this question, or the more general one...
Here's the code based on that answer:
import itertools
from random import shuffle
mylist = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T']
n=len(mylist)
k = n
m = 5
samples = set()
tries = 0
while len(samples) < m:
samples.add(tuple(random.sample(mylist,k)))
print (len(samples))
print(samples)
print(tries)

Python: Iterating through the columns in a list of list to find the palindromes

Here I have a word list as:
[['r', 'o', 't', 'o', 'r'], ['e', 'v', 'e', 'i', 'a'], ['f', 'i', 'n', 'e', 'd'], ['e', 'n', 'e', 't', 'a'], ['r', 'a', 't', 'e', 'r']]
And I have to display all the palindromes in this list which are in rows as well as columns.
I have coded to find all the palindromes in the rows. But cannot implement a method to find the palindromes in the columns.
Here is my code so far:
result_1=""
if len(palindrome)==len_line_str:
for row in range(len(palindrome)):
for horizontal_line in range(len(palindrome[row])):
if ''.join(palindrome[row])==''.join(reversed(palindrome[row])):
result_1=''.join(palindrome[row])+" is a palindrome starting at ["+str(row)+"]["+str(row)+"] and is a row in the table"
print(result_1)
Which will display the output:
rotor is a palindrome starting at [0][0] and is a row in the table
Where "rotor" is a palindrome.
I need a method to get the palindromes in the columns which are:
"refer", "tenet", "radar"
Any help is much appreciated. Thanks in advance!
You can use zip to transpose your lists:
>>> t = [['r', 'o', 't', 'o', 'r'], ['e', 'v', 'e', 'i', 'a'], ['f', 'i', 'n', 'e', 'd'], ['e', 'n', 'e', 't', 'a'], ['r', 'a', 't', 'e', 'r']]
[['r', 'o', 't', 'o', 'r'], ['e', 'v', 'e', 'i', 'a'], ['f', 'i', 'n', 'e', 'd'], ['e', 'n', 'e', 't', 'a'], ['r', 'a', 't', 'e', 'r']]
>>> list(zip(*t))
[('r', 'e', 'f', 'e', 'r'), ('o', 'v', 'i', 'n', 'a'), ('t', 'e', 'n', 'e', 't'), ('o', 'i', 'e', 't', 'e'), ('r', 'a', 'd', 'a', 'r')]
Your columns are now rows, and you can apply the same method than before. If you just need the words, you can use list comprehensions:
>>> rows = [['r', 'o', 't', 'o', 'r'], ['e', 'v', 'e', 'i', 'a'], ['f', 'i', 'n', 'e', 'd'], ['e', 'n', 'e', 't', 'a'], ['r', 'a', 't', 'e', 'r']]
>>> [''.join(row) for row in rows if row[::-1] == row ]
['rotor']
>>> [''.join(column) for column in zip(*rows) if column[::-1] == column ]
['refer', 'tenet', 'radar']
This will do the job:
palindrome=[['r', 'o', 't', 'o', 'r'], ['e', 'v', 'e', 'i', 'a'], ['f', 'i', 'n', 'e', 'd'], ['e', 'n', 'e', 't', 'a'], ['r', 'a', 't', 'e', 'r']]
n=len(palindrome)
for col in range(len(palindrome[0])):
col_word=[palindrome[i][col] for i in range(n)]
if ''.join(col_word)==''.join(reversed(col_word)):
result=''.join(col_word)+" is a palindrome starting at ["+str(col)+"] and is a col in the table"
print(result)
This prints
refer is a palindrome starting at [0] and is a col in the table
tenet is a palindrome starting at [2] and is a col in the table
radar is a palindrome starting at [4] and is a col in the table
Basically, in order to access the words in the column, you can do
col_word=[palindrome[i][col] for i in range(n)]
This fixes the column and iterates over the rows. The rest of the code is structures similarly to yours.
​
I saw you did not want to use Zip (which I would recommend using):
Alternative answer:
list_ = [['r', 'o', 't', 'o', 'r'], ['e', 'v', 'e', 'i', 'a'], ['f', 'i', 'n', 'e', 'd'], ['e', 'n', 'e', 't', 'a'], ['r', 'a', 't', 'e', 'r']]
You can get the palindromes (rows) by checking each list with the reversed list [::-1]:
[i==i[::-1] for i in list_]
# prints [True, False, False, False, False]
And get the palindromes (columns) by 1. create the column list (called list_2 below) with a list comprehension and 2. same principle as above:
list_2 = [[i[ind] for i in list_] for ind in range(len(list_))]
[i==i[::-1] for i in list_2]
# prints [True, False, True, False, True]
Update
If you want the answers directly you can do:
[i for i in list_ if i==i[::-1]]
# prints [['r', 'o', 't', 'o', 'r']]
# and list_2: [['r', 'e', 'f', 'e', 'r'],['t', 'e', 'n', 'e', 't'],['r', 'a', 'd', 'a', 'r']]
There are a lot of ways to do it. I will take as example your code because of your effort on it
Another alternative following your code, is creating the columns in another list and check wich of them are palindromes:
palindrome = [['r', 'o', 't', 'o', 'r'],
['e', 'v', 'e', 'i', 'a'],
['f', 'i', 'n', 'e', 'd'],
['e', 'n', 'e', 't', 'a'],
['r', 'a', 't', 'e', 'r']]
len_line_str = 5
result_1=""
def is_pal(string):
return string == reversed(string)
colums = []
if len(palindrome)==len_line_str:
for row in range(len(palindrome)):
vertical = []
if ''.join(palindrome[row])==''.join(reversed(palindrome[row])):
result_1+=''.join(palindrome[row])+" is a palindrome starting at ["+str(0)+"]["+str(row)+"] and is a row in the table. " + "\n"
for horizontal_line in range(len(palindrome[row])):
if(len_line_str-1 > horizontal_line):
vertical += [palindrome[horizontal_line][row]]
else:
vertical += [palindrome[horizontal_line][row]]
colums += [(vertical,row)]
for word in colums:
if ''.join(word[0])==''.join(reversed(word[0])):
result_1+=''.join(word[0])+" is a palindrome starting at ["+str(0)+"]["+str(word[1])+"] and is a column in the table" + "\n"
print(result_1)
This should work. First loop iterates through the list s and the second loop iterates through each list.
Assuming s is the name of the list- [['r', 'o', 't', 'o', 'r'], ['e', 'v', 'e', 'i', 'a'], ['f', 'i', 'n', 'e', 'd'], ['e', 'n', 'e', 't', 'a'], ['r', 'a', 't', 'e', 'r']]
for i in xrange(0,len(s),1):
str = ""
for j in s:
str = str + j[i]
print str
if str == str[::-1]:
print str," is a pallindrome - column", i
else:
print str," is not a pallindrome - column", i
There is no column wise traversal in Python. One hacky way you can follow is to perform transpose operation on your input matrix. Below is a simple way to implement transpose using list comprehensions.
def transpose(matrix):
if not matrix:
return []
return [[row[i] for row in matrix] for i in range(len(matrix[0]))]
Your same logic should work once modify your input using transpose.
Hope this helps!!

Categories