4

I'm currently learning Python.

How do I put this:

dates = list()  
for entry in some_list:  
    entry_split = entry.split()    
    if len(entry_split) >= 3:  
        date = entry_split[1]
        if date not in dates:  
            dates.append(date)

into a one-liner in Python?

dfernan
  • 377
  • 2
  • 9
  • 22
  • 9
    long one-liners are probably not the best thing to dive into for your first day in python. – Slater Victoroff Jun 19 '13 at 20:56
  • 3
    Why would you want to? It *can* be done, but the 1-liner is likely to be less efficient and harder to understand. 1-liners should only be used when they increase the clarity of the code. – mgilson Jun 19 '13 at 20:56
  • Could be still a lecit question! – Paolo Jun 19 '13 at 20:58
  • I agree with @SlaterTyranus - what you have looks good! – rickcnagy Jun 19 '13 at 20:58
  • @mgilson, list comprehensions will often be faster than building a list one item at a time, but this case doesn't look suitable for one due to the dependence on the partially created list. – Mark Ransom Jun 19 '13 at 21:08
  • For once, everyone seems to agree to stick with the code I've got. Will do and will keep in mind these suggestions. Thank you all! – dfernan Jun 19 '13 at 21:11
  • in my opinion, `if date not in dates` means it should not be a one liner. – Elazar Jun 19 '13 at 21:33
  • @MarkRansom -- Right. In this case, you would need to split the string multiple times though which would negate any speedups you'd gain from the list-comp. In any case though, the primary reason to use a list-comp is for code clarity, not speed. – mgilson Jun 19 '13 at 23:06

5 Answers5

6

Instead of a 1-liner, probably it's easier to understand with a 3-liner.

table = (entry.split() for entry in some_list)
raw_dates = (row[1] for row in table if len(row) >= 3)
# Uniquify while keeping order. http://stackoverflow.com/a/17016257
dates = list(collections.OrderedDict.fromkeys(raw_dates))
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • I get this error with `import collections`: `AttributeError: 'module' object has no attribute 'OrderedDict'`. Anything missing? – dfernan Jun 19 '13 at 21:17
  • 2
    @dfernandes__: You need to `import collections` first. And you need to use Python 2.7 or 3.x. – kennytm Jun 19 '13 at 21:18
  • Just updated to version 3.3.2, and your solution works as well. Thanks! – dfernan Jun 19 '13 at 21:39
3

If the order does not matter:

dates = set(split[1] for split in (x.split() for x in some_list) if len(split) >= 3)

Of course if you want a list instead of a set, just pass the result into list().

Although I would probably stick with what you have, as it is more readable.

Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
1

Try this, assuming that set comprehensions are available in your Python version:

list({d[1] for d in (e.split() for e in some_list) if len(d) >= 3})

If set comprehensions are not available, this will work:

list(set(d[1] for d in (e.split() for e in some_list) if len(d) >= 3))

But seriously, it's not a good idea to write this as a one-liner, for the reasons mentioned in the comments. Even so, your code can be improved a bit, use a set whenever you need to remove duplicates from a collection of elements:

dates = set()
for entry in some_list:
    entr_split = entry.split()
    if len(entry_split) >= 3:
        dates.add(entry_split[1])
dates = list(dates)
Óscar López
  • 232,561
  • 37
  • 312
  • 386
1

Seems to me that you are splitting every element in some_list, checking to see if the split element has 3 or more parts, and taking the second part and appending it to the list if it is not already in the list. You can use a set for this last behavior, since sets only contain unique elements.

list(set((entry_split[1] for entry_split in (entry.split() for entry in some_list) if len(entry_split) >= 3]))

I re-cast the result to a list because you used a list.

2rs2ts
  • 10,662
  • 10
  • 51
  • 95
0

Using a list comprehension:

dates = set([entry.split()[1] for entry in some_list if len(entry.split()) >= 3])

which gives us what we want:

>>> some_list = [
... "a 2011-08-04 b",
... "x y",
... "e 2012-03-04 g"
... ]
>>> dates = set([entry.split()[1] for entry in some_list if len(entry.split()) >= 3])
>>> dates
{'2011-08-24', '2012-03-04'}
brice
  • 24,329
  • 7
  • 79
  • 95