Related
So I need to define a function that returns a list that is arranged in a specific order, and also gives the amount of times each value appears.
For example, let's say i have this input:
["s", "w", "h", "s", "h"]
I'll need my function to return this:
[2, 2, 1]
The 2 is the amount of times s appears, the following 2 is the amount of times h appears, and the 1 is the amount of times w appears.
I have been stuck on this for quite a while now, this is how far I came:
def item_order(list):
sort_order = {"s": 0, "h": 1, "w": 2}
list.sort(key=lambda val: sort_order[val[1]])
But I'm not sure if this is the right way to go.
Any help would be greatly appreciated!
You can use collections.Counter to count number of items. For example:
from collections import Counter
def item_order(lst):
weights = {"s": 0, "h": 1, "w": 2}
rv = sorted(lst, key=weights.get)
return rv, Counter(rv)
lst = ["s", "w", "h", "s", "h"]
sorted_list, cnt = item_order(lst)
print(sorted_list)
print(cnt) # or list(cnt.values())
Prints:
['s', 's', 'h', 'h', 'w']
Counter({'s': 2, 'h': 2, 'w': 1})
# A set for values already seen
seen_characters = set()
# Function sorts a list of characters, calculates count of unique characters
# Parameter: list -> of characters
# Returns: list -> of numbers
def item_order(character_list):
result = []
character_list.sort()
for character in character_list:
if character not in seen_characters:
result.append(character_list.count(character))
seen_characters.add(character)
return result
given_list = ['s', 'w', 'h', 's', 'h']
print(item_order(given_list))
Hi please help me develop a logic which does following.
list_1 = [1,2,3]
list_2 = [a,b,c,d,e,f,g,h,i]
Required output (List of dictionaries):
output = [{1:a,2:b,3:c}, {1:d,2:e,3:f}, {1:g,2:h,3:i}]
My script:
return_list = []
k = 0
temp_dict = {}
for i, value in enumerate(list_2):
if k <= len(list_1)-1:
temp_dict[list_1[k]] = value
if k == len(list_1)-1:
k = 0
print temp_dict
return_list.append(temp_dict)
print return_list
print '\n'
else:
k = k + 1
print return_list
My output:
{1: 'a', 2: 'b', 3: 'c'}
[{1: 'a', 2: 'b', 3: 'c'}]
{1: 'd', 2: 'e', 3: 'f'}
[{1: 'd', 2: 'e', 3: 'f'}, {1: 'd', 2: 'e', 3: 'f'}]
{1: 'g', 2: 'h', 3: 'i'}
[{1: 'g', 2: 'h', 3: 'i'}, {1: 'g', 2: 'h', 3: 'i'}, {1: 'g', 2: 'h', 3: 'i'}]
[{1: 'g', 2: 'h', 3: 'i'}, {1: 'g', 2: 'h', 3: 'i'}, {1: 'g', 2: 'h', 3: 'i'}]
As you can see, temp_dict is getting printed correctly, but return_list is the last temp_dict 3 times.
please help to solve.
The issue here is that you are not reseting temp_dict to a new object.
When you append it to the list, it still maintains the reference to the dict object, after you change it on the next loop, it changes the value on the array because it's the same reference.
If you reset the value it should work
list_1 = [1,2,3]
list_2 = ['a','b','c','d','e','f','g','h','i']
return_list = []
k = 0
temp_dict = {}
for i, value in enumerate(list_2):
if k <= len(list_1)-1:
temp_dict[list_1[k]] = value
if k == len(list_1)-1:
k = 0
print temp_dict
return_list.append(temp_dict)
temp_dict = {} # Here is the change
print return_list
print '\n'
else:
k = k + 1
print return_list
This should work:
list_1 = [1,2,3]
list_2 = ['a','b','c','d','e','f','g','h','i']
output = []
j = 0
for i in range(1, len(list_1) + 1):
output.append(dict(zip(list_1, list_2[j:i * 3])))
j = i * 3
print(output)
The assumption is that you second list is exactly 3 times larger than the first list.
def merge_them(list1, list2):
output = []
i = 0
while i < len(list_2):
output.append(dict(zip(list_1, list_2[i: i + len(list1)])))
i += len(list1)
return output
and you can test it:
test1:
list_1 = [1,2,3]
list_2 = ['a','b','c','d','e','f','g','h','i']
print merge_them(list_1, list_2)
you will get:
[{1: 'a', 2: 'b', 3: 'c'}, {1: 'd', 2: 'e', 3: 'f'}, {1: 'g', 2: 'h', 3: 'i'}]
test2:
list_1 = [1,2,3,]
list_2 = ['a','b','c','d','e']
print merge_them(list_1, list_2)
you will get:
[{1: 'a', 2: 'b', 3: 'c'}, {1: 'd', 2: 'e'}]
test3:
list_1 = [1,2,3,4,5,6,7,8]
list_2 = ['a','b','c','d','e']
print merge_them(list_1, list_2)
you will get:
[{1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}]
Hi please help me develop a logic which does following.
list_1 = [1,2,3]
list_2 = [a,b,c,d,e,f,g,h,i]
Required output (List of dictionaries):
output = [{1:a,2:b,3:c}, {1:d,2:e,3:f}, {1:g,2:h,3:i}]
My script:
return_list = []
k = 0
temp_dict = {}
for i, value in enumerate(list_2):
if k <= len(list_1)-1:
temp_dict[list_1[k]] = value
if k == len(list_1)-1:
k = 0
print temp_dict
return_list.append(temp_dict)
print return_list
print '\n'
else:
k = k + 1
print return_list
My output:
{1: 'a', 2: 'b', 3: 'c'}
[{1: 'a', 2: 'b', 3: 'c'}]
{1: 'd', 2: 'e', 3: 'f'}
[{1: 'd', 2: 'e', 3: 'f'}, {1: 'd', 2: 'e', 3: 'f'}]
{1: 'g', 2: 'h', 3: 'i'}
[{1: 'g', 2: 'h', 3: 'i'}, {1: 'g', 2: 'h', 3: 'i'}, {1: 'g', 2: 'h', 3: 'i'}]
[{1: 'g', 2: 'h', 3: 'i'}, {1: 'g', 2: 'h', 3: 'i'}, {1: 'g', 2: 'h', 3: 'i'}]
As you can see, temp_dict is getting printed correctly, but return_list is the last temp_dict 3 times.
please help to solve.
return_list = []
k = 0
temp_dict = {}
for i, value in enumerate(list_2):
if k <= len(list_1)-1:
temp_dict[list_1[k]] = value
if k == len(list_1)-1:
k = 0
print temp_dict
return_list.append(temp_dict)
temp_dict = {}
else:
k = k + 1
For simple, you could use zip
list_1 = [1,2,3]
list_2 = ['a','b','c','d','e','f','g','h','i']
chunks = [list_2[idx:idx+3] for idx in range(0, len(list_2), 3)]
output = []
for each in chunks:
output.append(dict(zip(list_1, each)))
print(output)
from itertools import cycle
list_1 = [1, 2, 3]
list_2 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
def chunks(l, n):
for i in range(0, len(l), n):
yield l[i:i + n]
zipped = tuple(zip(cycle(list_1), list_2))
out = list(map(dict, chunks(zipped, len(list_1))))
print(out)
Gives you:
[{1: 'a', 2: 'b', 3: 'c'}, {1: 'd', 2: 'e', 3: 'f'}, {1: 'g', 2: 'h', 3: 'i'}]
I have two lists of unequal length such as
list1 = ['G','T','C','A','G']
list2 = ['AAAAA','TTTT','GGGG','CCCCCCCC']
I want to compare these two lists at each index only against the corresponding positions i.e list2[0] against list1[0] and list2[1] against list1[1] and so on upto the length of list1.
And get two new lists one having the mismatches and the second having the position of mismatches for example in the language of coding it can be stated as :
if 'G' == 'GGG' or 'G' # where 'G' is from list1[1] and 'GGG' is from list2[2]
elif 'G' == 'AAA'
{
outlist1 == list1[index] # postion of mismatch
outlist2 == 'G/A'
}
ok this works. There are definitely ways to do it in less code, but I think this is pretty clear:
#Function to process the lists
def get_mismatches(list1,list2):
#Prepare the output lists
mismatch_list = []
mismatch_pos = []
#Figure out which list is smaller
smaller_list_len = min(len(list1),len(list2))
#Loop through the lists checking element by element
for ind in range(smaller_list_len):
elem1 = list1[ind][0] #First char of string 1, such as 'G'
elem2 = list2[ind][0] #First char of string 2, such as 'A'
#If they match just continue
if elem1 == elem2:
continue
#If they don't match update the output lists
else:
mismatch_pos.append(ind)
mismatch_list.append(elem1+'/'+elem2)
#Return the output lists
return mismatch_list,mismatch_pos
#Make input lists
list1 = ['G','T','C','A','G']
list2 = ['AAAAA','TTTT','GGGG','CCCCCCCC']
#Call the function to get the output lists
outlist1,outlist2 = get_mismatches(list1,list2)
#Print the output lists:
print outlist1
print outlist2
Output:
['G/A', 'C/G', 'A/C']
[0, 2, 3]
And just to see how short I could get the code I made this function which I think is equivalent:
def short_get_mismatches(l1,l2):
o1,o2 = zip(*[(i,x[0]+'/'+y[0]) for i,(x,y) in enumerate(zip(l1,l2)) if x[0] != y[0]])
return list(o1),list(o2)
#Make input lists
list1 = ['G','T','C','A','G']
list2 = ['AAAAA','TTTT','GGGG','CCCCCCCC']
#Call the function to get the output lists
outlist1,outlist2 = short_get_mismatches(list1,list2)
EDIT:
I'm not sure if I'm cleaning the sequence as you want w/ the N's and -'s. Is this the answer to the example in your comment?
Unclean list1 ['A', 'T', 'G', 'C', 'A', 'C', 'G', 'T', 'C', 'G']
Clean list1 ['A', 'T', 'G', 'C', 'A', 'C', 'G', 'T', 'C', 'G']
Unclean list2 ['GGG', 'TTTN', '-', 'NNN', 'AAA', 'CCC', 'GCCC', 'TTT', 'CCCTN']
Clean list2 ['GGG', 'TTT', 'AAA', 'CCC', 'GCCC', 'TTT', 'CCCT']
0 A GGG
1 T TTT
2 G AAA
3 C CCC
4 A GCCC
5 C TTT
6 G CCCT
['A/G', 'G/A', 'A/G', 'C/T', 'G/C']
[0, 2, 4, 5, 6]
this works fine for my question:
#!/usr/bin/env python
list1=['A', 'T', 'G', 'C', 'A' ,'C', 'G' , 'T' , 'C', 'G']
list2=[ 'GGG' , 'TTTN' , ' - ' , 'NNN' , 'AAA' , 'CCC' , 'GCCC' , 'TTT' ,'CCCATN' ]
notifications = []
indexes = []
for i in range(min(len(list1), len(list2))):
item1 = list1[i]
item2 = list2[i]
# Skip ' - '
if item2 == ' - ':
continue
# Remove N since it's a wildcard
item2 = item2.replace('N', '')
# Remove item1
item2 = item2.replace(item1, '')
chars = set(item2)
# All matched
if len(chars) == 0:
continue
notifications.append('{}/{}'.format(item1, '/'.join(set(item2))))
indexes.append(i)
print(notifications)
print(indexes)
It gives the output as
['A/G', 'G/C', 'C/A/T']
[0, 6, 8]
I was looking for an algorithm for sorting an array in a custom way but I didn't succeed in finding the proper solution to my problem. I'll describe the code in Django-like syntax but it's not necessary to limit a solution only for Django.
Let's suppose I have the following models (classes):
class Website(models.Model):
...
class Offer(models.Model):
website = models.ForeignKey(Website, on_delete=models.CASCADE)
...
And let's suppose I have the following instances:
Offer 1 -> Website A
Offer 2 -> Website B
Offer 3 -> Website B
Offer 4 -> Website B
Offer 5 -> Website C
Offer 6 -> Website A
Offer 7 -> Website A
Offer 8 -> Website C
This instances form a sequence (array):
sequence = [Offer 1, Offer 2, Offer 3, Offer 4, Offer 5, Offer 6, Offer 7, Offer 8]
I need to sort the sequence in the way where Offers with the same Website cannot stand one after another nevertheless the original order should stay as same as possible.
So the sorted sequence should look this way:
sequence = [Offer 1, Offer 2, Offer 5, Offer 3, Offer 6, Offer 4, Offer 7, Offer 8]
Positive Examples:
Website A, Website B, Website A, Website C, Website A
Website A, Website B, Website C, Website B, Website C
Website A, Website B, Website A, Website B, Website A
Negative Examples:
Website A, Website B, Website B, Website A, Website B, ...
Website B, Website C, Website A, Website A, Website B, ...
Website B, Website C, Website A, Website C, Website C, ...
Thanks for any suggestion.
Try this:
def sort_custom(offers):
sorted_offers, sorted_count, index = [], len(offers), 0
while sorted_count > 0:
item = offers[index]
if not sorted_offers or sorted_offers[-1] != item:
sorted_offers.append(item)
sorted_count -= 1
del offers[index]
if index > 0: index = 0
else:
if index < len(offers) - 1:
index += 1
else:
sorted_offers += offers
break
return sorted_offers
Usage:
>> lst = ['A', 'B', 'B', 'B', 'C', 'A', 'A', 'C']
>> sort_custom(lst)
['A', 'B', 'C', 'B', 'A', 'B', 'A', 'C']
>> lst2 = ['C', 'A', 'C', 'A', 'C', 'A', 'A', 'A']
>> sort_custom(lst2)
['C', 'A', 'C', 'A', 'C', 'A', 'A', 'A']
timing:
>> # for lst = ['A', 'B', 'B', 'B', 'C', 'A', 'A', 'C']
>> timer.repeat(3, 2000000)
[0.4880218505859375, 0.4770481586456299, 0.4776880741119385]
This should work:
def gen_best_order(orig):
last = None
while len(orig) > 0:
deli = None
for i, m in enumerate(orig):
if m.website != last.website:
last = m
deli = i
yield m
break
if deli is None:
last = orig[0]
yield orig[0]
deli = 0
del orig[deli]
ordered = list(gen_best_order(sequence))
This is a generator that will try and yield elements in order, but if the next element equals the last element yielded, it will skip it. If it gets to the end of the list and there is no way to yield something that doesn't equal the previous, it just yields it anyway.
Here's an example of it working on a list of numbers:
def gen_best_order(orig):
last = None
while len(orig) > 0:
deli = None
for i, m in enumerate(orig):
if m != last:
last = m
deli = i
yield m
break
if deli is None:
last = orig[0]
yield orig[0]
deli = 0
del orig[deli]
nums = [1,2,3,3,4,5,5]
print 'orig:', nums
print 'reordered:', list(gen_best_order(nums))
This prints:
orig: [1, 2, 3, 3, 4, 5, 5]
reordered: [1, 2, 3, 4, 3, 5, 5]