List order manipulating in Python - python

I have two python lists as follow:
ListA = [a1,a2,a1,a3,a2,a4,a5,a4]
ListB = [b1,b2,b1,b3,b2,b4,b5,b4]
What I want is to find the equal elements in the two lists and print them in a file. I have found the equal elements in lists and add them to two new lists as follow:
[a1,a2,a4]
[b1,b2,b4]
I want to compare some parameters with elements in ListA and if an element in ListA and the parameter is equal print the corresponding element in ListB. I do this as follow.
for i,j in enumerate(ListA):
if j == paramname:
filelines.append('%sTransferSourceName = "%s"\n'%(indent,ListB[i]))
My problem is that the element are not in the order for ListB. It is added like below:
b2,b4,b1
So the whole order get mixed up.
Note that the number of letters in each element in the lists may differ.
Here is the code I have done so far:
def ProcessLinks():
duplicates = [x for x in linkparamArray if linkparamArray.count(x) > 1]
linkstemp = list(set(duplicates))
for i in linkstemp:
links.append(i)
def ProcessLinks2():
duplicates2 = [x for x in linkparameterArray if linkparameterArray.count(x) > 1]
linkstemp2 = list(set(duplicates2))
for j in linkstemp2:
linkparameters.append(j)
And here is the comparing code:
paramname = a1
for i,j in zip(linkparameters,links):
if i == paramname:
filelines.append('%s TransferSourceName = "%s"\n(indent,j))

You can use collections.Counter to determine duplicate elements.
>>> ListA = ['a1','a2','a1','a3','a2','a4','a5','a4']
>>> ListB = ['b1','b2','b1','b3','b2','b4','b5','b4']
>>> cB=collections.Counter(ListB)
>>> cA=x=collections.Counter(ListA)
>>> [i for i in cA if cA[i]>1]
['a1', 'a2', 'a4']
>>> [i for i in cB if cB[i]>1]
['b4', 'b1', 'b2']
As per the Comment of OP as the order is important than the following solution might work using (OrderedDict)[http://docs.python.org/library/collections.html#collections.OrderedDict]
dB=collections.OrderedDict()
dA=collections.OrderedDict()
>>> for a in ListB:
dB.setdefault(a,0)
dB[b]+=1
>>> for b in ListB:
dB.setdefault(b,0)
dB[b]+=1
>>> [i for i in dA if dA[i]>1]
['a1', 'a2', 'a4']
>>> [i for i in dB if dB[i]>1]
['b1', 'b2', 'b4']

By 'equal elements' do you mean repeated elements?
What is 'indent'?
The problem with using a dictionary is that you cannot have keys that are repeated. So if you were to build a dictionary using the two lists, the dictionary will contain only one entry (key, value pair) for each element in a list that is repeated.

Related

Comparing 2 lists and printing the differences

I am trying to compare 2 different lists and find the differences between them. Say for example I have list 1 which consists of cat,dog,whale,hamster and list 2 which consists of dog,whale,hamster. How would I compare these two and then assign a variable to the difference which in this case is cat. Order does not matter however if there is more than one difference each of these differences should be assigned to an individual variable.
In my actual code im comparing html which consists of thousands of lines so I would prefer something as fast as possible but any is appreciated :)
str1 = 'cat,dog,whale,hamster'
str2 = 'dog,whale,hamster'
Change strings into python sets:
set1 = set(str1.split(','))
set2 = set(str2.split(','))
Get the difference:
result = set1 - set2
Which prints:
{'cat'}
You can convert it to a list or a string:
result_as_list = list(result)
result_as_string = ','.join(result)
If your lists can contain duplicates or if you need to know the elements that are only in one of the two lists, you can use Counter (from the collections module):
list1 = ['cat','dog','whale','hamster','dog']
list2 = ['dog','whale','hamster','cow','horse']
from collections import Counter
c1,c2 = Counter(list1),Counter(list2)
differences = [*((c1-c2)+(c2-c1)).elements()]
print(differences) # ['cat', 'dog', 'cow', 'horse']
This is how you are gonna do it. The function defined here will print the difference between the two lists
def Diff(list1, list2):
li_dif = [i for i in list1 + list2 if i not in list1 or i not in list2]
return li_dif
# Driver Code
list1 = ['cat','dog','whale','hamster']
list2 = ['dog','whale','hamster']
diff = Diff(list1, list2)
print(diff)
output:
['cat']
here cat is generated by the variable diff
Now if there is more than one difference, as follows:
def Diff(list1, list2):
li_dif = [i for i in list1 + list2 if i not in list1 or i not in list2]
return li_dif
# Driver Code
list1 = ['cat','dog','whale','hamster','ostrich','yak','sheep','lion','tiger']
list2 = ['dog','whale','hamster']
diff = Diff(list1, list2)
print(diff)
the output will be:
['cat','ostrich','yak','sheep','lion','tiger']
Your question is that if there is more than one difference, each of these differences should be assigned to an individual variable.
for that, we will treat the printed item as a list, let's name it list3
diff==list3
here, list3=['cat','ostrich','yak','sheep','lion','tiger']
Here, is only 6 list items, we can assign a variable to each of them as follows:
v1=list3[0]
v2=list3[1]
v3=list3[2]
v4=list3[3]
v5=list3[4]
v6=list3[5]

How to change occurrence of the same element in a list next to each other without deleting the element in python?

I have two lists
list1=['A','B','C']
list2=['1','2','3']
I need a long list (combined by these 2 lists) of length 'n' without
any same pair consecutively ['A1','A1','C3','B2','B2',.....]
any same element of list1 consecutively ['A1','A2','A3','B1','B2',.......]
any same element of list2 consecutively ['A1','B1','C1','A2','B2',.......]
I want the elements of combined list in any order but without duplicates next to each other. In other words,
exactly like this for this example,
['A1','B2','C3','A2','B3','C1','A3','B1','C2','A1','B2','C3'.....]
Can someone please help me. I am looking for an answer since 2 days.
Edit:
I tried itertools method products.
newlist = [ n[0]+n[1] for n in list(itertools.product(list1,list2))]
#This gives the exact permutation of elements I need but not in the order I wish.
newlist = ['a1','a2','a3','b1','b2','b3','c1','c2','c3']
#Then, I used nested loops,
#To swap consecutive pairs elements in the newlist
for ind,n in enumerate(newlist):
while n == newlist[ind-1]:
for ind,n in enumerate(newlist):
while n == newlist[ind-1]:
newlist[ind-1],newlist[ind-2] = newlist[ind-2],newlist[ind-1]
#To swap consecutive list1 elements in the newlist
for ind,n in enumerate(newlist):
while n[0] == newlist[ind-1][0]:
for ind,n in enumerate(newlist):
while n[0] == newlist[ind-1][0]:
newlist[ind-1],newlist[ind-2] = newlist[ind-2],newlist[ind-1]
#To swap consecutive list2 elements in the newlist
for ind,n in enumerate(newlist):
while n[1] == newlist[ind-1][1]:
for ind,n in enumerate(newlist):
while n[1] == newlist[ind-1][1]:
newlist[ind-1],newlist[ind-2] = newlist[ind-2],newlist[ind-1]
Apparently, It works well with list with more than 3 elements. But not for the lists with length 3 and 2 respectively.
#Join the given list
list(map("".join,(zip(["A", "B", "C"], ["1","2","3"]))))
# Given your list
l3=["A1","B1","C1","A2","B2"]
l2=["A1","A2","A3","B1","B2"]
l=["A1","A1","C3","B2","B2"]
# set() data structure ensure no duplicate
list(set(l))+list(set(l2))+list(set(l3))
# output should be:
# ['B2', 'C3', 'A1', 'B2', 'A3', 'A2', 'B1', 'A1', 'C1', 'B2', 'A2', 'B1', 'A1']
Hope this help.
I have found a solution to what you want. A comment pointed by jrook showed a discussion similar to this but in their case it did not check to make sure it followed all the parameters you want. So i went ahead and wrote a little code for it.
import itertools
list1 = ["A","B","C"]
list2 = ["1","2","3", "4"]
if len(list1) < len(list2):
x = list1[:]
list1 = list2
list2 = x
list3 = [zip(x,list2) for x in itertools.permutations(list1,len(list2))]
new = []
for lis in list3:
for i in lis:
new.append(i[1] + i[0])
else:
list3 = [zip(x,list2) for x in itertools.permutations(list1,len(list2))]
new = []
for lis in list3:
for i in lis:
new.append(i[0] + i[1])
final = []
final.append(new[0])
new = new[1:]
def add_to(new, final):
if final[-1][0] != new[0][0] and final[-1][1] != new[0][1] and final[-1] != new[0]:
final.append(new[0])
new = new[1:]
else:
b = new[0]
new = new[1:]
new.append(b)
return new, final
while new != []:
new, final = add_to(new, final)
print(final)
the variable final is a list that will make sure that all the rules u want are followed, i.e: no duplicates, none of the same consecutive letter or number. Hope this is what you were looking for. I edited this so that now you can have the second or first list be of longer length and it will work just fine.
#declaring 2 lists
x=['a','b','c']
y=[str(n) for n in range(1,5)]
li=[]
#Creating the pairs by shuffling two lists
if len(x)>len(y):
for m in range(len(x)):
for n in range(len(y)):
li.append(x[m]+y[n-1])
m-=1
else:
for m in range(len(y)):
for n in range(len(x)):
li.append(y[m]+x[n-1])
m-=1
def pair_check(li):
for ind,val in enumerate(li):
if li[ind]==li[ind-1] or li[ind][0]==li[ind-1][0] or li[ind][1]==li[ind-1][1]:
return True
def pair_swap(li):
for ind,val in enumerate(li):
while li[ind]==li[ind-1] or li[ind][0]==li[ind-1][0] or li[ind][1]==li[ind-1][1]:
li[ind-len(x)],li[ind]=li[ind],li[ind-(len(x))]
#functions that verifies and swaps the pairs in combined list
while pair_check(li):
pair_swap(li)
print (li)
#Now the list li contains the list satisfies all the 3 conditions.

Matching and Combining Multiple 2D lists in Python

I am trying to combine (2) 2D lists based on a common value in both lists.
The values in the list are unique so there is nothing to take in to account for a list entry having any of the same values.
The example is:
list1 = [['hdisk37', '00f7e0b88577106a']]
list2 = [['1', '00f7e0b8cee02cd6'], ['2', '00f7e0b88577106a']]
With the desired result of:
list3 = [['hdisk37', '00f7e0b88577106a','2']]
The common value is at list1[0][1] and list2[1][1].
The pythonic way to get the needed result using set objects:
list1 = [['hdisk37', '00f7e0b88577106a']]
list2 = [['1', '00f7e0b8cee02cd6'], ['2', '00f7e0b88577106a']]
set1 = set(list1[0])
list3 = [list(set1 | s) for s in map(set, list2) if set1 & s]
print(list3)
The output:
[['00f7e0b88577106a', '2', 'hdisk37']]
set1 & s is intersection of two sets(returns a new set with elements common to the first set and all others)
set1 | s is union of a specified sets
Try this:
result = []
for inner_list1 in list1:
for inner_list2 in list2:
set1 = set(inner_list1)
set2 = set(inner_list1)
if set1.intersection(set2):
result.append(list(set1.union(set2)))
For each inner list in both lists, check if the intersection between them is not empty. In case it isn't, they are both merged and added to the final result.
This method returns all the possible "second value" matches as a dict, from the second value to the resulting list. It also takes an arbitrary number of these lists of lists (not just two).
import collections
a = [['hdisk37', '00f7e0b88577106a']]
b = [['1', '00f7e0b8cee02cd6'], ['2', '00f7e0b88577106a']]
def combine(*lols): # list of lists
ret = collections.defaultdict(set)
for lol in lols:
for l in lol:
ret[l[1]].add(l[1])
ret[l[1]].add(l[0])
return {k:list(v) for k,v in ret.items()}
print combine(a,b)
Output:
$ python test.py
{'00f7e0b8cee02cd6': ['00f7e0b8cee02cd6', '1'], '00f7e0b88577106a': ['hdisk37', '2', '00f7e0b88577106a']}
To get your exact output requested, you'd do:
combine(list1, list2).get('00f7e0b88577106a')
If you wanna try something different you could do a
merger = lambda x,y : set(x)|set(y) if set(x)&set(y) else x
results = []
for item in list1:
result = reduce(merger,[item]+list2)
if isinstance(result,set):
results.append(result)
print results

How to select a number without replacement in python

So I'm trying to make a mix and match between numbers here is my code
import random
P1 = float(input("Person's name?"))
P2 = float(input("Person's name?"))
P3 = float(input("Person's name?"))
A1 = float(input("Activity?"))
A2 = float(input("Activity?"))
A3 = float(input("Activity?"))
s = (A1, A2, A3)
cool1 = random.sample([A1, A2, A3],1)
cool2 = random.sample([A1, A2, A3],1)
cool3 = random.sample([A1, A2, A3],1)
print ("%s job is %s." %(P1, cool1))
print ("%s job is %s." %(P2, cool2))
print ("%s job is %s." %(P3, cool3))
The problem is that it is randomizing but it keeps repeating numbers like here
**
1.0 job is [4.0].
2.0 job is [5.0].
3.0 job is [4.0].
**
What can I do to make it not repeat.
I'm using python 2.7.12
Also how can I use alphanumerical instead of float only.
Best way to achieve this will be to use random.shuffle (if you want to randomize the original sample list) or random.select (if you want to keep the original sample copy):
Example with random.shuffle:
>>> import random
>>> my_samples = ['A1', 'A2', 'A3']
>>> shuffle(my_samples)
>>> cool1, cool2, cool3 = my_samples
# Random Result: cool1 = 'A3', cool2='A1', cool3='A2'
Example with random.select:
>>> cool1, cool2, cool3 = random.sample(['A1', 'A2', 'A3'], 3)
If you want minimal changes in your solution. You may remove an entry from your samples based on random selection and get next choice from remaining samples like:
>>> import random
>>> cool1 = random.sample(my_samples,1)
>>> my_samples.remove(*cool1)
>>> my_samples
['A1', 'A3']
>>> cool2 = random.sample(my_samples,1)
>>> my_samples.remove(*cool2)
>>> cool3 = random.sample(my_samples,1)
>>> my_samples.remove(*cool3)
>>> my_samples
[]
>>> cool1, cool2, cool3
(['A2'], ['A3'], ['A1'])
write a class to pick a unique element from list
1. permutations finds all unique elements
2. rest can define new data and length of result
from itertools import permutations
class PickOne( object ):
def __init__(self,lst,l):
self.lst = lst
self.visit = set()
self.l = l
self.lenght = self.number(l)
def pick(self):
if len(self.visit) == self.lenght :
print 'run out numbers'
return
res = tuple(random.sample(self.lst,self.l))
while res in self.visit:
res = tuple(random.sample(self.lst,self.l))
self.visit.add( res )
return res
def reset(self,l,lst = None):
if not lst:
lst = self.lst
self.__init__(lst,l)
def number(self,l):
return len( list(permutations(self.lst,l)) )
Example:
a = PickOne([1,2,3,4],1)
>>> a.pick()
(2,)
>>> a.pick()
(1,)
>>> a.pick()
(4,)
>>> a.pick()
(3,)
>>> a.pick()
run out numbers
>>> a.reset(2)
>>> a.pick()
(3, 1)
>>> a.pick()
(3, 4)
>>> a.pick()
(2, 1)
Since you are selecting from a list, then you should delete the entry from the list after each check.
Create your original list, which will be used as needed.
Create a second list from the first to use as you select.
As you choose each element from the list, remove it
Put the chosen element into a list of chosen element.
Python remove method
Parameters
obj -- This is the object to be removed from the list.
Return Value
This method does not return any value but removes the
given object from the list.
Example
The following example shows the usage of remove() method.
#!/usr/bin/python
aList = [123, 'xyz', 'zara', 'abc', 'xyz'];
aList.remove('xyz');
print "List : ", aList
aList.remove('abc');
print "List : ", aList
When we run above program, it produces following result −
List : [123, 'zara', 'abc', 'xyz']
List : [123, 'zara', 'xyz']
You could do this:
cool1, cool2, cool3 = random.sample([A1, A2, A3], 3)
Also how can I use alphanumerical instead of float only.
Have you tried not converting your inputs to float...?

list and elements comparison python

list1 = ['A','B']
list2 = ['a','c']
list3 = ['x','y','z']
list4 = [['A','b','c'],['a','x'],['Y','Z'],['d','g']]
I want to check if all elements of list (list1, list2, list3) is contained in any of list in another bigger list (list4).
I want the comparison to be case insensitive.
To be sure, here list1 and list2 is in list4 but not list3. How can I do it?
On the other note, How would I know if a list is collection of list.
In other words, how can I distinguish if list is a collection of list of just list of elements, if I am not the one who is defining the lists.
First item - you want to do case-insensitive matching. The best way to do that is to convert everything to one case (upper or lower). So for each list, run
list1 = map(lambda x: x.lower(), list1)
That will convert your lists to lowercase. Let's assume you've done that.
Second, for a comparison of two "simple" lists (not-nested), you can simply say
if set(list1) < set(list2):
to compare if list1 is a subset of list2. In your example, it would be false.
Finally, if you want to check if a list is nested:
if ( type(list4[0]) == list) :
which in this case, would be true. Then, just iterate over the elements of list4 and do the set comparison above.
You can use lower() to make all elements of all lists to lowercase to achieve case-insensitivity.
def make_case_insensitive(lst):
return [i.lower() for i in lst]
For example,
list1=make_case_insensitive(list1)
As, biggerlist is slightly different (contains list as element), you have to change the function slightly.
def make_bigger_list_caseinsensitive(bigger_list):
return [[i.lower() for i in element] for element in bigger_list]
list4=make_bigger_list_caseinsensitive(list4)
Check if any element of the biggerlist is the superset of smaller set. Print Is in bigger list if condition satisfied, print not in biggger list otherwise. Make set from the list first.
print "Is in bigger list" if any(set(element).issuperset(set(list1)) for element in list4) else "not in biggger list"
To write it with slightly more readability, do:
if any(set(element).issuperset(set(list1)) for element in list4):
print "Is in bigger list"
else:
print "not in biggger list"
Finally,to check if nested list exists in biggerlist:
print any(type(element)==list for element in list4)
Using set is a good way.
list1 = ['A','B']
list2 = ['a','c']
list3 = ['x','y','z']
list4 = [['A','b','c'],['a','x'],['Y','Z'],['d','g']]
set1 = set(map(lambda s: s.lower(), list1))
set2 = set(map(lambda s: s.lower(), list2))
set3 = set(map(lambda s: s.lower(), list3))
set4 = map(lambda l: set(map(lambda s: s.lower(), l)), list4)
print(set1) # set(['a', 'b'])
print(set2) # set(['a', 'c'])
print(set3) # set(['y', 'x', 'z'])
print(set4) # [set(['a', 'c', 'b']), set(['a', 'x']), set(['y', 'z']), set(['d', 'g'])]
lor = lambda x, y: x or y
reduce(lor, map(lambda s: set1.issubset(s), set4)) # True
reduce(lor, map(lambda s: set2.issubset(s), set4)) # True
reduce(lor, map(lambda s: set3.issubset(s), set4)) # False
To do a case-insensitive string comparison, covert both strings to lowercase or uppercase.
To test all elements in list1 are contained in list4, use set.issubset.

Categories

Resources