Can python create a dictionary from a list comprehension?

Discussion in 'Python' started by erikcw, May 27, 2007.

  1. erikcw

    erikcw Guest

    Hi,

    I'm trying to turn o list of objects into a dictionary using a list
    comprehension.

    Something like

    entries = {}
    [entries[int(d.date.strftime('%m'))] = d.id] for d in links]

    I keep getting errors when I try to do it. Is it possible? Do
    dictionary objects have a method equivalent to [].append? Maybe a
    lambda?

    Thanks for your help!
    Erik
     
    erikcw, May 27, 2007
    #1
    1. Advertising

  2. erikcw

    Guest

    On May 27, 1:55 pm, erikcw <> wrote:
    > Hi,
    >
    > I'm trying to turn o list of objects into a dictionary using a list
    > comprehension.
    >
    > Something like
    >
    > entries = {}
    > [entries[int(d.date.strftime('%m'))] = d.id] for d in links]
    >
    > I keep getting errors when I try to do it. Is it possible? Do
    > dictionary objects have a method equivalent to [].append? Maybe a
    > lambda?
    >
    > Thanks for your help!
    > Erik


    try...

    [entries.__setitem__(int(d.date.strftime('%m'))], d.id) for d in
    links]

    btw...I was curious of this too. I used 'dir(dict)' and looked for a
    method that might do what we wanted and bingo!

    ~Sean
     
    , May 27, 2007
    #2
    1. Advertising

  3. erikcw schrieb:
    > Hi,
    >
    > I'm trying to turn o list of objects into a dictionary using a list
    > comprehension.
    >
    > Something like
    >
    > entries = {}
    > [entries[int(d.date.strftime('%m'))] = d.id] for d in links]
    >
    > I keep getting errors when I try to do it. Is it possible? Do
    > dictionary objects have a method equivalent to [].append? Maybe a
    > lambda?
    >
    > Thanks for your help!
    > Erik
    >
    >

    normally a dict(whatEver) will do ;-)

    Example:

    a = [1,2,3,4,5,6,7,8,9,10]

    aDict = dict([(x,x+1) for x in a if x%2==0])

    print aDict
     
    Stefan Sonnenberg-Carstens, May 27, 2007
    #3
  4. On 27 mai, 22:55, erikcw <> wrote:
    > Hi,
    >
    > I'm trying to turn o list of objects into a dictionary using a list
    > comprehension.
    >
    > Something like
    >
    > entries = {}
    > [entries[int(d.date.strftime('%m'))] = d.id] for d in links]
    >
    > I keep getting errors when I try to do it. Is it possible? Do
    > dictionary objects have a method equivalent to [].append? Maybe a
    > lambda?
    >
    > Thanks for your help!
    > Erik


    entries = dict([ (int(d.date.strftime('%m')),d.id) for d in links] )

    With Python2.4 and above you can use a "generator expression"

    entries = dict( (int(d.date.strftime('%m')),d.id) for d in links )


    Regards,
    Pierre
     
    Pierre Quentel, May 27, 2007
    #4
  5. In <>, half.italian
    wrote:

    > [entries.__setitem__(int(d.date.strftime('%m'))], d.id) for d in
    > links]
    >
    > btw...I was curious of this too. I used 'dir(dict)' and looked for a
    > method that might do what we wanted and bingo!


    This is really ugly. Except `__init__()` it's always a code smell if you
    call a "magic" method directly instead of using the corresponding
    syntactic sugar or built in function. And using a list comprehension just
    for side effects is misleading because the reader expects a (useful) list
    to be build when stumbling over a list comp and it's wasteful because an
    unnecessary list of `None`\s is build and thrown away for no reason other
    than to have a one liner. This is not Perl! ;-)

    Ciao,
    Marc 'BlackJack' Rintsch
     
    Marc 'BlackJack' Rintsch, May 28, 2007
    #5
  6. erikcw

    Wim Vogelaar Guest

    > Example:
    >
    > a = [1,2,3,4,5,6,7,8,9,10]
    >
    > aDict = dict([(x,x+1) for x in a if x%2==0])
    >
    > print aDict
    >


    When I run this program I get:
    {8: 9, 2: 3, 4: 5, 10: 11, 6: 7}

    why this output isn't ordered, giving:
    {2: 3, 4: 5, 6: 7, 8: 9, 10: 11 }
     
    Wim Vogelaar, May 28, 2007
    #6
  7. Pierre Quentel a écrit :
    > On 27 mai, 22:55, erikcw <> wrote:
    >> Hi,
    >>
    >> I'm trying to turn o list of objects into a dictionary using a list
    >> comprehension.

    ....
    >
    > entries = dict([ (int(d.date.strftime('%m')),d.id) for d in links] )
    >
    > With Python2.4 and above you can use a "generator expression"
    >
    > entries = dict( (int(d.date.strftime('%m')),d.id) for d in links )
    >


    You can also create dictionaries knowing only the keys the same way (ie.
    a two-dimensional array) :

    In [77]: dict.fromkeys((a, b) for a in range(4) for b in range(2))
    Out[78]:
    {(0, 0): None,
    (0, 1): None,
    (1, 0): None,
    (1, 1): None,
    (2, 0): None,
    (2, 1): None,
    (3, 0): None,
    (3, 1): None}
     
    Maric Michaud, May 28, 2007
    #7
  8. erikcw

    Tim Churches Guest

    Flags of the world

    http://shaheeilyas.com/flags/

    Scroll to the bottom to see why this is not entirely off-topic. Are
    there other public examples in which Python has been used to harvest and
    represent public information in useful and/or interesting ways? Ideas
    for some more?

    Tim C
     
    Tim Churches, May 28, 2007
    #8
  9. erikcw

    Wim Vogelaar Guest


    >
    > why this output isn't ordered, giving:
    > {2: 3, 4: 5, 6: 7, 8: 9, 10: 11 }
    >
    >


    I made the original list two elements longer: a =
    [1,2,3,4,5,6,7,8,9,10,11,12]

    and to my surprise the output is now ordered, giving: {2: 3, 4: 5, 6: 7, 8:
    9, 10: 11, 12: 13}

    I am running ActiveState ActivePython 2.5
     
    Wim Vogelaar, May 28, 2007
    #9
  10. En Mon, 28 May 2007 05:20:16 -0300, Wim Vogelaar
    <> escribió:

    >> Example:
    >>
    >> a = [1,2,3,4,5,6,7,8,9,10]
    >>
    >> aDict = dict([(x,x+1) for x in a if x%2==0])
    >>
    >> print aDict
    >>

    >
    > When I run this program I get:
    > {8: 9, 2: 3, 4: 5, 10: 11, 6: 7}
    >
    > why this output isn't ordered, giving:
    > {2: 3, 4: 5, 6: 7, 8: 9, 10: 11 }


    A dictionary is not ordered, no matter how you create it. If you want to
    process the keys in order:

    for key in sorted(aDict):
    print key, '=', aDict[key]

    (Note that sorted(aDict) returns a *list*, not a dictionary!)

    --
    Gabriel Genellina
     
    Gabriel Genellina, May 28, 2007
    #10
  11. erikcw

    Guest

    On May 28, 12:25 am, Marc 'BlackJack' Rintsch <> wrote:
    > In <>, half.italian
    > wrote:
    >
    > > [entries.__setitem__(int(d.date.strftime('%m'))], d.id) for d in
    > > links]

    >
    > > btw...I was curious of this too. I used 'dir(dict)' and looked for a
    > > method that might do what we wanted and bingo!

    >
    > This is really ugly. Except `__init__()` it's always a code smell if you
    > call a "magic" method directly instead of using the corresponding
    > syntactic sugar or built in function. And using a list comprehension just
    > for side effects is misleading because the reader expects a (useful) list
    > to be build when stumbling over a list comp and it's wasteful because an
    > unnecessary list of `None`\s is build and thrown away for no reason other
    > than to have a one liner. This is not Perl! ;-)
    >
    > Ciao,
    > Marc 'BlackJack' Rintsch


    It's ugly I agree, but it was the first solution I found. I need you
    guys for the _right_ solutions :) I have stumbled over the same
    situation myself. I don't see that the list comprehension itself is
    misleading. If nothing is catching the empty list that is returned,
    it signals that the returned list is unimportant, and if wrapped by a
    call to dict() its obvious also.

    Do you think we just shouldn't use list comprehensions to build
    dictinaries at all? Or is Stefan's solution acceptable (and pythonic)?

    ~Sean
     
    , May 28, 2007
    #11
  12. erikcw

    Peter Otten Guest

    wrote:

    > Do you think we just shouldn't use list comprehensions to build
    > dictinaries at all? Or is Stefan's solution acceptable (and pythonic)?


    Use list comprehensions where you need the resulting list; if you want
    nothing but the side effects, use a for loop.

    [Stefan Sonnenberg-Carstens]
    > a = [1,2,3,4,5,6,7,8,9,10]
    > aDict = dict([(x,x+1) for x in a if x%2==0])


    Stefan's example meets the above criterion, so yes, it's acceptable. In
    Python 2.5 you would use a generator expression, though:

    aDict = dict((x, x+1) for x in a if x % 2 ==0)

    Peter
     
    Peter Otten, May 28, 2007
    #12
  13. En Mon, 28 May 2007 05:37:12 -0300, Wim Vogelaar
    <> escribió:

    > I made the original list two elements longer: a =
    > [1,2,3,4,5,6,7,8,9,10,11,12]
    >
    > and to my surprise the output is now ordered, giving: {2: 3, 4: 5, 6: 7,
    > 8:
    > 9, 10: 11, 12: 13}
    >
    > I am running ActiveState ActivePython 2.5


    Keys in a dictionary are listed in an arbitrary order; the *only* thing
    about the ordering you can say is that, given a FIXED dictionary (already
    constructed, and without any other intervening operation that could alter
    its content), when you iterate over its keys (using .keys(), .iterkeys()),
    its values (.values(), .itervalues()) or items (.items(), .iteritems())
    you will always get the same things in the same order over and over.
    If you create the dictionary using a different sequence of insertions and
    deletions, you may get different results. If you insert and delete things
    afterwards, you may get different results. If you exit the program and run
    it again, you may get different results. The *only* guaranteed fact is
    that you will get the same results provided you don't modify the
    dictionary at all.

    See note (3) in http://docs.python.org/lib/typesmapping.html

    --
    Gabriel Genellina
     
    Gabriel Genellina, May 28, 2007
    #13
  14. erikcw

    Duncan Booth Guest

    "Wim Vogelaar" <wim.vogelaar at mc2world dot org> wrote:

    >
    >>
    >> why this output isn't ordered, giving:
    >> {2: 3, 4: 5, 6: 7, 8: 9, 10: 11 }
    >>
    >>

    >
    > I made the original list two elements longer: a =
    > [1,2,3,4,5,6,7,8,9,10,11,12]
    >
    > and to my surprise the output is now ordered, giving: {2: 3, 4: 5, 6:
    > 7, 8: 9, 10: 11, 12: 13}
    >

    .... and it will become unordered again when you get up to storing 32 in the
    dictionary, and ordered again when you get up to 44.

    It is an unfortunate side-effect of the way that Python dictionaries work
    that it often appears when you store small integers as though they are
    being stored sorted. In fact the order depends on the order in which you
    inserted the values into the dictionary, the current size allocated to the
    dictionary, and whether any slots have previously been occupied by other
    values.

    In your original output:

    {8: 9, 2: 3, 4: 5, 10: 11, 6: 7}

    the keys 2, 4, and 6 are inserted into the 2nd, 4th, 6th slots of the
    dictionary (counting from 0 and there are initially 8 slots), 8 goes into
    the 0th slot, 10 would go into the 2nd slot except that is filled so it
    ends up in the 5th slot.

    When you insert 12, the initial dictionary is too full (it never fills all
    the slots), so it is resized to have 32 slots. Again the 32 wraps round to
    the 0th slot and higher values all collide with filled slots so they end up
    in less obvious positions:

    >>> for i in range(12,42,2):

    print dict.fromkeys(range(2,i,2))


    {8: None, 2: None, 4: None, 10: None, 6: None}
    {2: None, 4: None, 6: None, 8: None, 10: None, 12: None}
    {2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None}
    {2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16:
    None}
    {2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16:
    None, 18: None}
    {2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16:
    None, 18: None, 20: None}
    {2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16:
    None, 18: None, 20: None, 22: None}
    {2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16:
    None, 18: None, 20: None, 22: None, 24: None}
    {2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16:
    None, 18: None, 20: None, 22: None, 24: None, 26: None}
    {2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16:
    None, 18: None, 20: None, 22: None, 24: None, 26: None, 28: None}
    {2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16:
    None, 18: None, 20: None, 22: None, 24: None, 26: None, 28: None, 30: None}
    {32: None, 2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14:
    None, 16: None, 18: None, 20: None, 22: None, 24: None, 26: None, 28: None,
    30: None}
    {32: None, 2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 34:
    None, 14: None, 16: None, 18: None, 20: None, 22: None, 24: None, 26: None,
    28: None, 30: None}
    {32: None, 2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 34:
    None, 14: None, 16: None, 18: None, 20: None, 22: None, 24: None, 36: None,
    26: None, 28: None, 30: None}
    {32: None, 2: None, 4: None, 38: None, 6: None, 8: None, 10: None, 12:
    None, 34: None, 14: None, 16: None, 18: None, 20: None, 22: None, 24: None,
    36: None, 26: None, 28: None, 30: None}

    The fact that integers hash to themselves may be unlikely to change, but
    the sizes of the hash tables, or the conflict resolution strategy when an
    insertion hits an already used slot could all vary in other versions of
    Python.
     
    Duncan Booth, May 28, 2007
    #14
  15. erikcw

    Ben Finney Guest

    Re: Flags of the world

    Tim Churches <> writes:

    > http://shaheeilyas.com/flags/
    >
    > Scroll to the bottom to see why this is not entirely off-topic.


    I fail to see what it has to do with the thread you're replyiing to,
    which is a discussion of creating a dictionary from a list
    comprehension.

    If you want to start a new thread, compose a new message, not a reply
    to an existing thread.

    --
    \ "If you ever catch on fire, try to avoid seeing yourself in the |
    `\ mirror, because I bet that's what REALLY throws you into a |
    _o__) panic." -- Jack Handey |
    Ben Finney
     
    Ben Finney, May 28, 2007
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Eric @ Zomething

    Can a List Comprehension do ____ ?

    Eric @ Zomething, Jul 14, 2004, in forum: Python
    Replies:
    6
    Views:
    266
    Duncan Booth
    Jul 15, 2004
  2. Shane Geiger
    Replies:
    4
    Views:
    391
    bullockbefriending bard
    Mar 25, 2007
  3. Replies:
    6
    Views:
    1,383
    Dustan
    Jun 13, 2007
  4. Debajit Adhikary
    Replies:
    17
    Views:
    693
    Debajit Adhikary
    Oct 18, 2007
  5. Vedran Furac(
    Replies:
    4
    Views:
    331
    Marc 'BlackJack' Rintsch
    Dec 19, 2008
Loading...

Share This Page