Print statements won't execute after the for loop - python

"""
ID: kunalgu1
LANG: PYTHON3
TASK: ride
"""
fin = open ('ride.in', 'r')
fout = open ('ride.out', 'w')
lines = fin.readlines()
cometString = lines[0]
cometValue = 1
groupString = lines[1]
groupValue = 1
def orderS (val):
arrL = ['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']
arrN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
indexVal = arrL.index(val.lower())
return arrN[indexVal]
for x in cometString:
print(orderS(x))
cometValue *= orderS(x)
print(cometValue)
Here is the main error: it won't print
cometValue = cometValue % 47
print(cometValue)
fout.close()

The loop gets an error because the lines returned by readlines() include the newline terminator. When it calls orderS() for that character, arrL.index() fails because there's no newline in arrL.
You can remove the newline with the rstrip() method:
cometString = lines[0].rstrip()
You could also have orderS() return a default value when the character can't be found:
def orderS (val):
arrL = ['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']
arrN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
try:
indexVal = arrL.index(val.lower())
return arrN[indexVal]
except ValueError:
return 27

Related

How can I efficiently randomly select items from a dictionary that meet my requirements?

So at the moment, I have a large dictionary of items. Might be a little confusing, but each of these keys have different values, and the values themselves correspond to another dictionary.
I need to make sure that my random selection from the first dict covers all possible values in the second dict. I'll provide a rudimentary example:
Dict_1 = {key1: (A, C), key2: (B, O, P), key3: (R, T, A)} # and so on
Dict_2 = {A: (1, 4, 7), B: (9, 2, 3), C: (1, 3)} # etc
I need a random selection of Dict_1 to give me a coverage of all numbers from 1 - 10 in Dict_2 values.
At the moment, I am selecting 6 random keys from Dict_1, taking all the numbers that those letters would correspond with, and comparing that set to a set of the numbers from 1 - 10. If the selection isn't a subset of 1 - 10, select 6 more random ones and try again, until I have 1 - 10.
Now, this works, but I know it's far from efficient. How can I improve this method?
I am using Python.
At the moment, I am selecting 6 random keys from Dict_1, taking all the numbers that those letters would correspond with, and comparing that set to a set of the numbers from 1 - 10. If the selection isn't a subset of 1 - 10, select 6 more random ones and try again, until I have 1 - 10.
Now, this works, but I know it's far from efficient. How can I improve this method?
In case your solution doesn't fully cover 1-10, you're erasing the whole solution and restarting completely from scratch.This is what's inefficient.
Instead, you could use an approach inspired by simulated annealing or random nearest neighbour search. The idea is that if your solution doesn't fully cover 1-10, then instead of erasing it, you try to incrementally make it better.
One way to do this is to attribute a score to each of the six keys in your solution. This score should reflect how useful that key is in the solution; i.e., how many numbers in 1-10 are covered thanks to this key that are not already covered by another key.
Then, instead of picking six new random keys, you keep the five best keys and only pick one new random key. The solution should become incrementally better, until hopefully it covers the whole range 1-10.
import random
keylist1 = ['key{}'.format(n) for n in range(100)]
keylist2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
cover_range = range(1,21) # 1-20 instead of 1-10 otherwise the problem is too simple
d1 = {k: random.choices(keylist2, 3) for k in keylist1}
# d1 = {'key0': ['N', 'C', 'L'], 'key1': ['P', 'N', 'M'], 'key2': ['I', 'G', 'Q'], 'key3': ['F', 'M', 'R'], 'key4': ['L', 'P', 'U'], 'key5': ['V', 'Q', 'L'], 'key6': ['R', 'W', 'K'], 'key7': ['T', 'S', 'I'], 'key8': ['W', 'M', 'T'], 'key9': ['A', 'K', 'Q'], 'key10': ['J', 'I', 'L'], 'key11': ['F', 'X', 'D'], 'key12': ['L', 'J', 'B'], 'key13': ['A', 'W', 'I'], 'key14': ['L', 'R', 'Y'], 'key15': ['V', 'O', 'Z'], 'key16': ['G', 'U', 'B'], 'key17': ['R', 'G', 'S'], 'key18': ['X', 'C', 'V'], 'key19': ['S', 'F', 'Z'], 'key20': ['J', 'S', 'L'], 'key21': ['E', 'P', 'X'], 'key22': ['L', 'X', 'E'], 'key23': ['B', 'L', 'O'], 'key24': ['B', 'T', 'W'], 'key25': ['H', 'V', 'Y'], 'key26': ['J', 'T', 'C'], 'key27': ['M', 'G', 'A'], 'key28': ['I', 'E', 'P'], 'key29': ['L', 'R', 'N'], 'key30': ['V', 'J', 'B'], 'key31': ['I', 'V', 'T'], 'key32': ['E', 'N', 'W'], 'key33': ['W', 'D', 'M'], 'key34': ['E', 'Q', 'P'], 'key35': ['C', 'Z', 'A'], 'key36': ['T', 'X', 'O'], 'key37': ['B', 'D', 'J'], 'key38': ['N', 'M', 'D'], 'key39': ['E', 'B', 'A'], 'key40': ['A', 'B', 'K'], 'key41': ['Z', 'B', 'O'], 'key42': ['G', 'L', 'A'], 'key43': ['P', 'N', 'H'], 'key44': ['Z', 'W', 'M'], 'key45': ['K', 'A', 'J'], 'key46': ['O', 'B', 'L'], 'key47': ['J', 'Z', 'F'], 'key48': ['C', 'D', 'O'], 'key49': ['F', 'B', 'J'], 'key50': ['H', 'V', 'T'], 'key51': ['A', 'L', 'O'], 'key52': ['N', 'T', 'Q'], 'key53': ['F', 'N', 'D'], 'key54': ['K', 'W', 'V'], 'key55': ['A', 'M', 'E'], 'key56': ['Z', 'J', 'A'], 'key57': ['S', 'B', 'W'], 'key58': ['D', 'S', 'P'], 'key59': ['E', 'Y', 'H'], 'key60': ['C', 'S', 'Y'], 'key61': ['L', 'P', 'M'], 'key62': ['H', 'S', 'N'], 'key63': ['S', 'U', 'J'], 'key64': ['J', 'N', 'R'], 'key65': ['E', 'B', 'W'], 'key66': ['B', 'V', 'Q'], 'key67': ['K', 'V', 'L'], 'key68': ['N', 'Z', 'H'], 'key69': ['O', 'U', 'E'], 'key70': ['E', 'W', 'H'], 'key71': ['W', 'P', 'A'], 'key72': ['G', 'W', 'X'], 'key73': ['Z', 'D', 'Q'], 'key74': ['S', 'Y', 'P'], 'key75': ['C', 'A', 'I'], 'key76': ['E', 'V', 'S'], 'key77': ['F', 'M', 'T'], 'key78': ['L', 'E', 'S'], 'key79': ['E', 'T', 'J'], 'key80': ['J', 'Y', 'A'], 'key81': ['I', 'F', 'G'], 'key82': ['D', 'S', 'L'], 'key83': ['F', 'E', 'P'], 'key84': ['X', 'L', 'T'], 'key85': ['H', 'U', 'M'], 'key86': ['W', 'A', 'C'], 'key87': ['Z', 'L', 'K'], 'key88': ['Y', 'N', 'X'], 'key89': ['F', 'K', 'B'], 'key90': ['Q', 'G', 'W'], 'key91': ['U', 'O', 'W'], 'key92': ['N', 'C', 'L'], 'key93': ['O', 'V', 'P'], 'key94': ['D', 'Y', 'R'], 'key95': ['S', 'K', 'I'], 'key96': ['G', 'Y', 'R'], 'key97': ['T', 'Z', 'G'], 'key98': ['C', 'A', 'Q'], 'key99': ['H', 'I', 'W']}
d2 = {c: random.sample(cover_range, 3) for c in keylist2}
# d2 = {'A': [14, 10, 17], 'B': [11, 20, 15], 'C': [11, 9, 8], 'D': [6, 18, 19], 'E': [18, 7, 1], 'F': [9, 14, 12], 'G': [17, 18, 20], 'H': [17, 12, 8], 'I': [17, 7, 5], 'J': [8, 20, 5], 'K': [17, 7, 13], 'L': [1, 18, 20], 'M': [5, 8, 18], 'N': [15, 17, 10], 'O': [16, 20, 18], 'P': [2, 18, 7], 'Q': [11, 17, 6], 'R': [3, 15, 4], 'S': [5, 15, 6], 'T': [6, 15, 20], 'U': [20, 12, 8], 'V': [20, 16, 3], 'W': [2, 16, 1], 'X': [5, 11, 1], 'Y': [2, 9, 8], 'Z': [6, 3, 16]}
import random
from collections import Counter
from itertools import chain
def random_solution():
solution = set(random.sample(keylist1, 6))
coverage = Counter(chain.from_iterable(d2[c] for k in solution for c in d1[k]))
while len(coverage) < len(cover_range):
#print(solution, ' ', sorted(coverage.keys()))
scores = {k: sum(1/coverage[n] for n in frozenset().union(*(d2[c] for c in d1[k])) ) for k in solution}
#print(scores)
worst_key = min(solution, key=scores.get)
solution.remove(worst_key)
while len(solution) < 6:
solution.add(random.choice(keylist1)) # in while loop just because the new random key might be one of the 5 keys we already had, if we're unlucky
coverage = Counter(chain.from_iterable(d2[c] for k in solution for c in d1[k]))
return solution

fPython : Making a new list from a random list of letters

letters = ['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']#alphabet
bag_o_letters = []#letters to chose from
letter_count = [9, 2, 2, 4, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 4, 2, 2, 1, 2, 1]#random indexes to chose from
for x in range(26):#loops through the random index of letter_count
for i in range(letter_count[x]):#chooses the index
bag_o_letters.append(letters[x])#appends the index of the letter to bag_o_letters
rack = []#list for the person to see
for a in range(7):#makes the list 7 letters long
rack.append(bag_o_letters.pop(random.randint(0,len(letters)-1)))#appends the letter to rack(supposedly...)
print(rack)
In this code that you just read it should choose random letters and put 7 of those letters in a rack that the person can see. It shows a error that I've looked over many times, but I just can't see what is wrong.
I put comments on the side to understand the code.
It shows this error:
rack.append(bag_of_letters.pop(random.randint(0,len(letters)-1)))
IndexError: pop index out of range
Can someone please help?
After this code, I am going to make a input statement for the user to make a word from those letters.
The first time through the loop, you append one value to bag_of_letters, and then you try to pop an index of random.randint(0,len(letters)-1). It doesn't have that many elements to pop from yet. Instead of this approach, you can make a list of the required length and sample from it:
letters = ['a', ...]#alphabet
letter_count = [9, ...]#random indexes to chose from
bag_of_letters = [l*c for l,c in zip(letters, letter_count)]
...
rack = random.sample(bag_o_letters, 7)
You're selecting the index to pop for bag_of_letters from the length of letters which is obviously larger.
You should instead do:
rack.append(bag_of_letters.pop(random.randint(0, len(bag_of_letters)-1)))
# ^^^^^^^^^^^^^^
However, there are likely to be more problems with your code. I'll suggest you use random.sample in one line of code or random.shuffle on a copy of the list, and then slice up till index 7. Both will give you 7 randomly selected letters:
import random
print(random.sample(letters, 7))
# ['m', 'u', 'l', 'z', 'r', 'd', 'x']
import random
letters = ['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']
letters_copy = letters[:]
random.shuffle(letters_copy)
print(letters_copy[:7])
# ['c', 'e', 'x', 'b', 'w', 'f', 'v']
The IndexError is expected:
pop(...)
L.pop([index]) -> item -- remove and return item at index (default last).
Raises IndexError if list is empty or index is out of range.
You need to subtract 1 from the bounds of the call to random() after each pop(). Right now you are doing this:
l = [1,2,3]
random_idx = 2
l.pop(random_idx)
>>> l == [1,3]
random_idx = 3
l.pop(random_idx)
>>>> IndexError: pop index out of range
So instead, pop() based on len(bag_o_letter) rather than len(letter).
Why not do something like this:
letters = ['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']
letter_count = [9, 2, 2, 4, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 4, 2, 2, 1, 2, 1]#random indexes to chose from
from random import shuffle
all_letters = list(''.join([l*c for l,c in zip(letters, letter_count)]))
shuffle(all_letters)
for i in range(int(len(all_letters)/7)):
print all_letters[i*7:(i+1)*7]
So I assume this is for something like scrabble? Your issue is that you're choosing a random index from your list of letters, not bag_o_letters. Maybe try this:
rack = []
for i in range(7):
index = random.randint(0, len(bag_o_letter) - 1)
rack.append(bag_o_letters.pop(index))

Find longest non-breaking common elements in a list

I have this list which contain only Ws and Ss:
ls = ['W', 'S', 'S', 'S', 'W', 'W', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'W', 'W', 'W', 'W', 'W', 'W', 'S']
What I want to do is to extract the longest nonbreaking "S" in that list?
and return the index of that Ss, returning:
['S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S']
and
[6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
How can I achieve that?
Use itertools.groupby with enumerate and max:
>>> from operator import itemgetter
>>> from itertools import groupby
>>> val = max((list(g) for k, g in
groupby(enumerate(ls), itemgetter(1)) if k == 'S'), key=len)
>>> indices, items = zip(*val)
>>> indices
(6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
>>> items
('S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S')
Same solution as Ashwini Chaudhary's minus the elegance,
from itertools import groupby
index, result, m_index = 0, [], 0
# Group based on the elements of the list
for item, grp in groupby(ls):
# Get the grouped items as a list
grp = list(grp)
# Filter out `M`s and check if this is the biggest run of `S`s ever seen
if item == "S" and len(grp) > len(result):
result, m_index = grp, index
# Increment the index to keep track of the list covered
index += len(grp)
print(result, list(range(m_index, m_index + len(result))))
>>> import re
>>> max((x.group(), x.span()) for x in re.finditer("S+", "".join(ls)))
('SSSSSSSSSSS', (6, 17))
>>> range(6, 17)
[6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
package com.algo.sort;
public class LargestCont{
static int g[]={1,1,1,1,2,2,3,4,5,5,5,5,5,5,5,5,5,5,5,2,2,2,2,3,3,3,3,3,3,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0};
public static void main(String f[]){
manage(g);
}
public static void manage(int[] j){
int max=1; int val=-1; int count=0; int ans=0;
for(int i=0;i<j.length;i++){
if(j[i]!=val){
if(max>count){
ans=val;
count=max;
System.out.println(ans+"...."+count);
}
val=j[i]; max=1;}else{
max++;
}
}
System.out.println(ans);
}
}
ls = ['W', 'S', 'S', 'S', 'W', 'W', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'W', 'W', 'W', 'W', 'W', 'W', 'S']
for x,y in enumerate(ls):
print (x,str(y).split("W"))
I found this one.

Coding words as products of integers

I am trying to write a program that checks if smaller words are found within a larger word. For example, the word "computer" contains the words "put", "rum", "cut", etc. To perform the check I am trying to code each word as a product of prime numbers, that way the smaller words will all be factors of the larger word. I have a list of letters and a list of primes and have assigned (I think) an integer value to each letter:
letters = ['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']
primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
61, 67, 71, 73, 79, 83, 89, 97, 101]
index = 0
while index <= len(letters)-1:
letters[index] = primes[index]
index += 1
The problem I am having now is how to get the integer code for a given word and be able to create the codes for a whole list of words. For example, I want to be able to input the word "cab," and have the code generate its integer value of 5*2*3 = 30.
Any help would be much appreciated.
from functools import reduce # only needed for Python 3.x
from operator import mul
primes = [
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101
]
lookup = dict(zip("abcdefghijklmnopqrstuvwxyz", primes))
def encode(s):
return reduce(mul, (lookup.get(ch, 1) for ch in s.lower()))
then
encode("cat") # => 710
encode("act") # => 710
Edit: more to the point,
def is_anagram(s1, s2):
"""
s1 consists of the same letters as s2, rearranged
"""
return encode(s1) == encode(s2)
def is_subset(s1, s2):
"""
s1 consists of some letters from s2, rearranged
"""
return encode(s2) % encode(s1) == 0
then
is_anagram("cat", "act") # => True
is_subset("cat", "tactful") # => True
I would use a dict here to look-up the prime for a given letter:
In [1]: letters = ['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']
In [2]: primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
61, 67, 71, 73, 79, 83, 89, 97, 101]
In [3]: lookup = dict(zip(letters, primes))
In [4]: lookup['a']
Out[4]: 2
This will let you easily determine the list of primes for a given word:
In [5]: [lookup[letter] for letter in "computer"]
Out[5]: [5, 47, 41, 53, 73, 71, 11, 61]
To find the product of those primes:
In [6]: import operator
In [7]: reduce(operator.mul, [lookup[letter] for letter in "cab"])
Out[7]: 30
You've got your two lists set up, so now you just need to iterate over each character in a word and determine what value that letter gives you.
Something like
total = 1
for letter in word:
index = letters.index(letter)
total *= primes[index]
Or whichever operation you decide to use.
You would generalize that to a list of words.
Hmmmm... It isn't very clear how this code is supposed to run. If it is built to find words in the english dictionary, think about using PyEnchant, a module for checking if words are in the dictionary. Something you could try is this:
letters = ['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']
primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101]
word = raw_input('What is your word? ')
word = list(word)
total = 1
nums = []
for k in word:
nums.append(primes[letters.index(k)])
for k in nums:
total = total*k
print total
This will output as:
>>> What is your word? cat
710
>>>
This is correct, as 5*2*71 equals 710

Extract specific data entries(as groups) from a list and store in separate lists?

For example, here is a sample of the list i am looping over,
['n', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 82, 83, 84, 85, 86, 87, 88, 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', ''n', 'n', 'n', 178, 179, 180]
This list is generated from a previously called function(the n's have been inserted to hide unwanted values).
I am attempting to group the numbers which are separated between n's and send them to a list, for instance take the numbers 1-37->put in a list, take numbers 82-88->different list, 178-180->send to different list.
The tricky part is that the list will not always have the same set of data inside, the 'groups' can be of arbitrary size and location. The only defining feature is that they are separated by n's.
My attempt so far:
for i in range(0, len(lists)):
for index, item in enumerate(lines):
if item != 'n': #if item is not n send to list
lists[i].append(item)
elif lines[index+1] == 'n':#if the next item is an n
del lines[:index]
Where 'lists' is actually a list of lists created outside this function, to store each of the groups, the number of lists is determined by the number of groups that is needed to be stored.
'lines' is the list of values I wish to loop over.
My logic is, all values that is not an 'n' append in the first list, if the next value is an n, then delete all values before and loop over the new list putting the next set of values into the next list. so on.
except I get: list index out of range
Which I understand, but I was hoping there was a way to hack around it. I have also tried breaking out of the loop at the elif, but then I cannot continue the loop where I left off.
My final attempt was to restart the loop at a location set after the first run like so:
place=0
for i in range(0, len(lists)):
for index, item in enumerate(lines[place:]):
if item != 'n': #if item is not n send to list
lists[i].append(item)
elif lines[index+1] == 'n':#if the next item is an n
place=[index]
break
slice indices must be integers or None or have an index method
Hope that was clear, Can anyone lend a hand?
from itertools import groupby
data = ['n', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 82, 83, 84, 85, 86, 87, 88, 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 178, 179, 180]
def keyfunc(n):
return n == 'n'
groups = [list(g) for k, g in groupby(data, keyfunc) if not k]
>>> import itertools
>>> data = ['n', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 82, 83, 84, 85, 86, 87, 88, 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 178, 179, 180]
>>> [list(g) for k, g in itertools.groupby(data, lambda x: x != 'n') if k]
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37],
[82, 83, 84, 85, 86, 87, 88],
[178, 179, 180]]
This works:
li=['n', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 82, 83, 84, 85, 86, 87, 88, 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 178, 179, 180]
from itertools import groupby
def is_n(c): return c=='n'
print [list(t1) for t0,t1 in groupby(li, is_n) if t0==False]
Prints:
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37], [82, 83, 84, 85, 86, 87, 88], [178, 179, 180]]
If you want to do this 'raw' (without itertools) this works:
def is_n(c): return c=='n'
def divide(li, f):
r=[]
while li:
while li and f(li[0]):
li.pop(0)
sub=[]
while li and not f(li[0]):
sub.append(li.pop(0))
r.append(sub)
return r
print divide(li,is_n)
Or, if you want to use a for loop:
def divide4(li,f):
r=[]
sub=[]
for e in li:
if f(e):
if len(sub)==0:
continue
else:
r.append(sub)
sub=[]
else:
sub.append(e)
else:
if len(sub): r.append(sub)
return r
print divide4(li,is_n)
Either case, prints:
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37], [82, 83, 84, 85, 86, 87, 88], [178, 179, 180]]
itertools is faster, easier, proven. Use that.

Categories

Resources