Re: dict comprehension question.

2013-01-01 Thread 88888 Dihedral
On Tuesday, January 1, 2013 11:10:48 AM UTC+8, Steven D'Aprano wrote:
 On Sat, 29 Dec 2012 18:56:57 -0500, Terry Reedy wrote:
 
 
 
  On 12/29/2012 2:48 PM, Quint Rankid wrote:
 
  
 
  Given a list like:
 
  w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
 
  I would like to be able to do the following as a dict comprehension. 
 
  a = {}
 
  for x in w:
 
   a[x] = a.get(x,0) + 1
 
  results in a having the value:
 
  {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}
 
  
 
  Let me paraphrase this: I have nice, clear, straightforward,
 
  *comprehensible* code that I want to turn into an incomprehensible mess
 
  with a 'comprehension. That is the ironic allure of comprehensions.
 
 
 
 But... but... one liner! ONE LINNR Won't somebody think 
 
 of the lines I'll save
 
 
 
 *wink*
 
 
 
 
 
 In case it's not obvious, I'm 100% agreeing with Terry here. List comps 
 
 and dict comps are wonderful things, but they can't do everything, and 
 
 very often even if they can do something they shouldn't because it makes 
 
 the code inefficient or unreadable.
 
 
 
 There's nothing wrong with a two or three liner.
 
 
 
 
 
 
 
 -- 
 
 Steven

This is useful for not being choked in sorting a list
by the notorious quick-sort.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: dict comprehension question.

2012-12-31 Thread Steven D'Aprano
On Sat, 29 Dec 2012 18:56:57 -0500, Terry Reedy wrote:

 On 12/29/2012 2:48 PM, Quint Rankid wrote:
 
 Given a list like:
 w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
 I would like to be able to do the following as a dict comprehension. 
 a = {}
 for x in w:
  a[x] = a.get(x,0) + 1
 results in a having the value:
 {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}
 
 Let me paraphrase this: I have nice, clear, straightforward,
 *comprehensible* code that I want to turn into an incomprehensible mess
 with a 'comprehension. That is the ironic allure of comprehensions.

But... but... one liner! ONE LINNR Won't somebody think 
of the lines I'll save

*wink*


In case it's not obvious, I'm 100% agreeing with Terry here. List comps 
and dict comps are wonderful things, but they can't do everything, and 
very often even if they can do something they shouldn't because it makes 
the code inefficient or unreadable.

There's nothing wrong with a two or three liner.



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


dict comprehension question.

2012-12-29 Thread Quint Rankid
Newbie question.  I've googled a little and haven't found the answer.

Given a list like:
w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
I would like to be able to do the following as a dict comprehension.
a = {}
for x in w:
a[x] = a.get(x,0) + 1
results in a having the value:
{1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}

I've tried a few things
eg
a1 = {x:self.get(x,0)+1 for x in w}
results in error messages.

And
a2 = {x:a2.get(x,0)+1 for x in w}
also results in error messages.

Trying to set a variable to a dict before doing the comprehension
a3 = {}
a3 = {x:a3.get(x,0)+1 for x in w}
gets this result, which isn't what I wanted.
{1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1}

I'm not sure that it's possible to do this, and if not, perhaps the
most obvious question is what instance does the get method bind to?

TIA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: dict comprehension question.

2012-12-29 Thread Roy Smith
In article 
724d4fea-606a-4503-b538-87442f6bc...@ci3g2000vbb.googlegroups.com,
 Quint Rankid qbr...@gmail.com wrote:

 Newbie question.  I've googled a little and haven't found the answer.
 
 Given a list like:
 w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
 I would like to be able to do the following as a dict comprehension.
 a = {}
 for x in w:
 a[x] = a.get(x,0) + 1

Why are you trying to do this mind-blowing thing?  Other than as an 
entry in an obfuscated code contest, what is this for?

Anyway, I don't think this is possible with a dict comprehension.  
Entries in the dict depend on entries previously put into the dict.  I 
don't see any way a dict comprehension can deal with this.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: dict comprehension question.

2012-12-29 Thread Mitya Sirenef

On 12/29/2012 02:48 PM, Quint Rankid wrote:

Newbie question.  I've googled a little and haven't found the answer.

Given a list like:
w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
I would like to be able to do the following as a dict comprehension.
a = {}
for x in w:
 a[x] = a.get(x,0) + 1
results in a having the value:
{1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}

I've tried a few things
eg
a1 = {x:self.get(x,0)+1 for x in w}
results in error messages.

And
a2 = {x:a2.get(x,0)+1 for x in w}
also results in error messages.

Trying to set a variable to a dict before doing the comprehension
a3 = {}
a3 = {x:a3.get(x,0)+1 for x in w}
gets this result, which isn't what I wanted.
{1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1}

I'm not sure that it's possible to do this, and if not, perhaps the
most obvious question is what instance does the get method bind to?

TIA


Will this do?:

 w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
 {x: w.count(x) for x in w}
{1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}


 - mitya

--
Lark's Tongue Guide to Python: http://lightbird.net/larks/

--
http://mail.python.org/mailman/listinfo/python-list


Re: dict comprehension question.

2012-12-29 Thread Mitya Sirenef

On 12/29/2012 03:01 PM, Mitya Sirenef wrote:

On 12/29/2012 02:48 PM, Quint  Rankid wrote:

 Newbie question. I've googled a little and haven't found the answer.

 Given a list like:
 w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
 I would like to be able to do the following as a dict comprehension.
 a = {}
 for x in w:
 a[x] = a.get(x,0) + 1
 results in a having the value:
 {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}

 I've tried a few things
 eg
 a1 = {x:self.get(x,0)+1 for x in w}
 results in error messages.

 And
 a2 = {x:a2.get(x,0)+1 for x in w}
 also results in error messages.

 Trying to set a variable to a dict before doing the comprehension
 a3 = {}
 a3 = {x:a3.get(x,0)+1 for x in w}
 gets this result, which isn't what I wanted.
 {1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1}

 I'm not sure that it's possible to do this, and if not, perhaps the
 most obvious question is what instance does the get method bind to?

 TIA

 Will this do?:

  w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
  {x: w.count(x) for x in w}
 {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}


 - mitya


I should probably add that this might be inefficient for large lists as
it repeats count for each item. If you need it for large lists, profile
against the 'for loop' version and decide if performance is good enough
for you, for small lists it's a nice and compact solution.

In a more general case, you can't refer to the list/dict/etc
comprehension as it's being constructed, that's just not a design goal
of comprehensions.

 -m

--
Lark's Tongue Guide to Python: http://lightbird.net/larks/

--
http://mail.python.org/mailman/listinfo/python-list


Re: dict comprehension question.

2012-12-29 Thread Joel Goldstick
On Sat, Dec 29, 2012 at 3:09 PM, Mitya Sirenef msire...@lightbird.netwrote:

 On 12/29/2012 03:01 PM, Mitya Sirenef wrote:

 On 12/29/2012 02:48 PM, Quint  Rankid wrote:

  Newbie question. I've googled a little and haven't found the answer.
 
  Given a list like:
  w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
  I would like to be able to do the following as a dict comprehension.
  a = {}
  for x in w:
  a[x] = a.get(x,0) + 1
  results in a having the value:
  {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}
 
  I've tried a few things
  eg
  a1 = {x:self.get(x,0)+1 for x in w}
  results in error messages.
 
  And
  a2 = {x:a2.get(x,0)+1 for x in w}
  also results in error messages.
 
  Trying to set a variable to a dict before doing the comprehension
  a3 = {}
  a3 = {x:a3.get(x,0)+1 for x in w}
  gets this result, which isn't what I wanted.
  {1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1}
 
  I'm not sure that it's possible to do this, and if not, perhaps the
  most obvious question is what instance does the get method bind to?
 
  TIA
 
  Will this do?:
 
   w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
   {x: w.count(x) for x in w}
  {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}
 
 
  - mitya
 

 I should probably add that this might be inefficient for large lists as
 it repeats count for each item. If you need it for large lists, profile
 against the 'for loop' version and decide if performance is good enough
 for you, for small lists it's a nice and compact solution.

 In a more general case, you can't refer to the list/dict/etc
 comprehension as it's being constructed, that's just not a design goal
 of comprehensions.


Would this help:

  w = [1,2,3,1,2,4,4,5,6,1]
  s = set(w)
  s
 set([1, 2, 3, 4, 5, 6])
  {x:w.count(x) for x in s}
 {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}



  -m


 --
 Lark's Tongue Guide to Python: http://lightbird.net/larks/

 --
 http://mail.python.org/**mailman/listinfo/python-listhttp://mail.python.org/mailman/listinfo/python-list




-- 
Joel Goldstick
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: dict comprehension question.

2012-12-29 Thread Peter Otten
Quint Rankid wrote:

 Newbie question.  I've googled a little and haven't found the answer.
 
 Given a list like:
 w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
 I would like to be able to do the following as a dict comprehension.
 a = {}
 for x in w:
 a[x] = a.get(x,0) + 1
 results in a having the value:
 {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}
 
 I've tried a few things
 eg
 a1 = {x:self.get(x,0)+1 for x in w}
 results in error messages.
 
 And
 a2 = {x:a2.get(x,0)+1 for x in w}
 also results in error messages.
 
 Trying to set a variable to a dict before doing the comprehension
 a3 = {}
 a3 = {x:a3.get(x,0)+1 for x in w}
 gets this result, which isn't what I wanted.
 {1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1}
 
 I'm not sure that it's possible to do this, and if not, perhaps the
 most obvious question is what instance does the get method bind to?

The name a3 will not be rebound until after the right side is evaluate. To 
spell it with a loop:

a3 = {}
_internal = {} # You have no access to this var. 
   # Even if you can beat a particular 
   # Python implementation -- you shouldn't

for x in w:
_internal[x] = a3.get(x, 0) + 1

a3 = _internal

That should make it clear that x will be looked up in the old empty a3 
dict.

The closest you can get to a self-updating dict is probably

 w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
 a1 = {}
 a1.update((x, a1.get(x, 0)+1) for x in w)
 a1
{1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}

but that it works doesn't mean it is a good idea. 
If your Python version supports it the obvious choice is

 from collections import Counter
 w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
 Counter(w)
Counter({1: 3, 2: 2, 4: 2, 3: 1, 5: 1, 6: 1})


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: dict comprehension question.

2012-12-29 Thread MRAB

On 2012-12-29 19:48, Quint Rankid wrote:

Newbie question.  I've googled a little and haven't found the answer.

Given a list like:
w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
I would like to be able to do the following as a dict comprehension.
a = {}
for x in w:
 a[x] = a.get(x,0) + 1
results in a having the value:
{1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}

I've tried a few things
eg
a1 = {x:self.get(x,0)+1 for x in w}
results in error messages.

And
a2 = {x:a2.get(x,0)+1 for x in w}
also results in error messages.

Trying to set a variable to a dict before doing the comprehension
a3 = {}
a3 = {x:a3.get(x,0)+1 for x in w}
gets this result, which isn't what I wanted.
{1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1}

I'm not sure that it's possible to do this, and if not, perhaps the
most obvious question is what instance does the get method bind to?


You can't do it with a comprehension.

The best way is probably with the 'Counter' class:

 w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
 from collections import Counter
 Counter(w)
Counter({1: 3, 2: 2, 4: 2, 3: 1, 5: 1, 6: 1})

If you want the result be a dict, then just the result to 'dict':

 dict(Counter(w))
{1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}

--
http://mail.python.org/mailman/listinfo/python-list


Re: dict comprehension question.

2012-12-29 Thread Mitya Sirenef

On 12/29/2012 03:15 PM, Joel Goldstick wrote:




On Sat, Dec 29, 2012 at 3:09 PM, Mitya Sirenef msire...@lightbird.net 
mailto:msire...@lightbird.net wrote:


On 12/29/2012 03:01 PM, Mitya Sirenef wrote:

On 12/29/2012 02:48 PM, Quint  Rankid wrote:

 Newbie question. I've googled a little and haven't found the
answer.

 Given a list like:
 w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
 I would like to be able to do the following as a dict
comprehension.
 a = {}
 for x in w:
 a[x] = a.get(x,0) + 1
 results in a having the value:
 {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}

 I've tried a few things
 eg
 a1 = {x:self.get(x,0)+1 for x in w}
 results in error messages.

 And
 a2 = {x:a2.get(x,0)+1 for x in w}
 also results in error messages.

 Trying to set a variable to a dict before doing the comprehension
 a3 = {}
 a3 = {x:a3.get(x,0)+1 for x in w}
 gets this result, which isn't what I wanted.
 {1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1}

 I'm not sure that it's possible to do this, and if not, perhaps the
 most obvious question is what instance does the get method bind to?

 TIA

 Will this do?:

  w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
  {x: w.count(x) for x in w}
 {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}


 - mitya


I should probably add that this might be inefficient for large
lists as
it repeats count for each item. If you need it for large lists,
profile
against the 'for loop' version and decide if performance is good
enough
for you, for small lists it's a nice and compact solution.

In a more general case, you can't refer to the list/dict/etc
comprehension as it's being constructed, that's just not a design goal
of comprehensions.


Would this help:

  w = [1,2,3,1,2,4,4,5,6,1]
  s = set(w)
  s
 set([1, 2, 3, 4, 5, 6])
  {x:w.count(x) for x in s}
 {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}




Indeed, this is much better -- I didn't think of it..


--
Lark's Tongue Guide to Python: http://lightbird.net/larks/

--
http://mail.python.org/mailman/listinfo/python-list


Re: dict comprehension question.

2012-12-29 Thread Terry Reedy

On 12/29/2012 4:40 PM, Mitya Sirenef wrote:

On 12/29/2012 03:15 PM, Joel Goldstick wrote:



Would this help:

  w = [1,2,3,1,2,4,4,5,6,1]
  s = set(w)
  s
 set([1, 2, 3, 4, 5, 6])
  {x:w.count(x) for x in s}
 {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}




Indeed, this is much better -- I didn't think of it..


It still turns an O(n) problem into an O(k*n) problem, where k is the 
number of distinct items.


--
Terry Jan Reedy

--
http://mail.python.org/mailman/listinfo/python-list


Re: dict comprehension question.

2012-12-29 Thread Terry Reedy

On 12/29/2012 2:48 PM, Quint Rankid wrote:


Given a list like:
w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
I would like to be able to do the following as a dict comprehension.
a = {}
for x in w:
 a[x] = a.get(x,0) + 1
results in a having the value:
{1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}


Let me paraphrase this: I have nice, clear, straightforward, 
*comprehensible* code that I want to turn into an incomprehensible mess 
with a 'comprehension. That is the ironic allure of comprehensions.


Comprehensions do not allow for interactions between the source items. 
Mitya and Joel worked around this with solutions that do redundant 
calculation and multiply the time order.


Reductions do allow for interactions. Doing everything as a reduction 
was the fad before comprehensions came along ;-)


from functools import reduce
w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
def update(dic, n):
Mutate and return dic (contrary to usual Python policy)
dic[n] = dic.get(n, 0) + 1
return dic
counts = reduce(update, w, {})
print(counts == {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1})

# prints True

The above is how to rewrite your code in a functional language that does 
not have statements and explicit iteration. In Python, I would only 
bother to wrap the body of the loop in a function if I needed the same 
body in multiple places.


Comprehensions are filtered mappings and that both filter and map can be 
written as reduction, so reduction included comprehension. It is more 
powerful because it can also do sequential interaction. Indeed, I would 
say that it should only be used when there is sequential interaction.


--
Terry Jan Reedy

--
http://mail.python.org/mailman/listinfo/python-list


Re: dict comprehension question.

2012-12-29 Thread Tim Chase

On 12/29/12 15:40, Mitya Sirenef wrote:

   w = [1,2,3,1,2,4,4,5,6,1]
   s = set(w)
   s
  set([1, 2, 3, 4, 5, 6])
   {x:w.count(x) for x in s}
  {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}


Indeed, this is much better -- I didn't think of it..


Except that you're still overwhelmed by iterating over every element 
in w for every distinct element.  So you've gone from O(N**2) to 
O(k*N).


The cleanest way to write it (IMHO) is MRAB's

  w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
  from collections import Counter
  results = dict(Counter(w))

which should gather all the statistics in one single pass across w 
making it O(N), and it's Pythonically readable.


-tkc



--
http://mail.python.org/mailman/listinfo/python-list


Re: dict comprehension question.

2012-12-29 Thread Joel Goldstick
On Sat, Dec 29, 2012 at 7:26 PM, Tim Chase python.l...@tim.thechases.comwrote:

 On 12/29/12 15:40, Mitya Sirenef wrote:

w = [1,2,3,1,2,4,4,5,6,1]
s = set(w)
s
   set([1, 2, 3, 4, 5, 6])
{x:w.count(x) for x in s}
   {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}


 Indeed, this is much better -- I didn't think of it..


 Except that you're still overwhelmed by iterating over every element in
 w for every distinct element.  So you've gone from O(N**2) to O(k*N).

 The cleanest way to write it (IMHO) is MRAB's


   w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
   from collections import Counter
   results = dict(Counter(w))

 which should gather all the statistics in one single pass across w
 making it O(N), and it's Pythonically readable.

 -tkc

 I like this too.  I haven't learned about collections module yet.  Thanks
for the pointer



 --
 http://mail.python.org/**mailman/listinfo/python-listhttp://mail.python.org/mailman/listinfo/python-list




-- 
Joel Goldstick
-- 
http://mail.python.org/mailman/listinfo/python-list