1

I have this list:

names = ['john','Jonh','james','James','Jardel']

I want loop over the list and handle consecutive names with a case insensitive match in the same iteration. So in the first iteration I would do something with'john' and 'John' and I want the next iteration to start at 'james'.

I can't think of a way to do this using Python's for loop, any suggestions?

3
  • What would you do in the case the names are not consecutive, ie ` ["jo", "Jim", "jim", "Jo"]` ?
    – OscarRyz
    Commented May 3, 2010 at 18:22
  • 1
    Your second name is Jonh. I suppose that's a typo and it should be John?
    – extraneon
    Commented May 3, 2010 at 18:23
  • Personally I'd build a set of names, all lower cased, thus removing the doubles, and capitalize as needed. But that might not meet your requirements.
    – extraneon
    Commented May 3, 2010 at 18:25

5 Answers 5

6

This would be one for itertools.groupby, which groups consecutive equal elements from a list or other iterable. you can specify a function to do the comparison, so that, in your case, the same name in different cases can still be counted as the same thing.

for k, g in itertools.groupby(names, lambda s: s.lower()):
    # Example: in the first iteration:
    #  k = "john"
    #  g = an iterator over ["john", "John"]
    # Process them as you like
4
  • How do I use the g var? I tried to print it but I get this: <itertools._grouper object at 0x00B619D0> I'm obviously a noob in python so please don't hate me :)
    – hdx
    Commented May 3, 2010 at 18:54
  • That's because it's an iterator object. You could use it in a for loop or a list comprehension (like [name for name in g]) and you'll get the names out of it, but if you try to use it without iterating over it, it'll just show up as an iterator, as you saw. To print out the list of names, you could use print list(g) which converts it to a list before printing.
    – David Z
    Commented May 3, 2010 at 19:00
  • 1
    g is an iterator over the items in the current group. You could iterate over it in a for loop or a list comprehension or turn it into a list with list(g). One possible thing to do would be to print out the names in the current group separated by commas: print ', '.join(g), which works because the join method works with any iterable. Commented May 3, 2010 at 19:03
  • 1
    @hdx: perhaps it helps to know that input to groupby() must be sorted. The list you show is sorted in a case-insensitive manner, but if it wasn't then you can do something like: for k,g in groupby(sorted(names, key=lambda x:x.lower()), lambda x: x.lower()): Commented May 3, 2010 at 19:44
2
names = ['john','John','james','James']
for name, capitalized_name in zip(names[::2], names[1::2]):
    print name, capitalized_name

Note that you need an even amount of items for this to work properly.

Or (maybe better; hard to tell with little context) use a set to filter the list to contain only unique names (note that this loses order):

>>> names = ['john','John','james','James','Jardel']
>>> unique_names = set([x.lower() for x in names])
>>> for unique_name in unique_names:
...     print unique_name
... 
jardel
james
john
0

You could just use a while loop:

i = 0
while i < len(names):
  # compare names[i] with names[i + 1]
  i = i + 2 # or + 1 if names not equal, for example

Or are you looking for something a bit more involved?

0

As you iterate thru the loop, you could try keeping track of the previous name in the list. At the same time, when you're going to store the names, you can make a call to lower() or capitalize() to make the formatting of each name consistent so that you can compare them easier.

e.g.

first = True
prev= ""
for name in names:
    if first:                         #First iteration
        prev = name.lower()           #Need to get the first elem
        do_something_to(curr)
        first = False
    else:
        if prev == name.lower():
             print "do nothing"
        else:
             do_something_to(curr)
        prev = name.lower()

May not be the most efficient, but works.

0

My $0.02:

def byPairs(li):
    for i in xrange(1, len(li), 2):
        yield (li[i-1], li[i])

for a,b in byPairs(names):
    if a.lower()==b.lower():
        doSomething(a,b)

I'm not sure I understood the question exactly; what are you trying to accomplish?

Not the answer you're looking for? Browse other questions tagged or ask your own question.