Python is still awesome

Just because I just came across it while optimizing some old code, I have to mention this.
I have the following list of dictionaries (array or hash-arrays in other words) and I want to sum up the values of one of the items of the dictionary.

In python I do this


    d = [{'value':1, 'title':'one'}, {'value':2}, {'value':3},
         {'value':4, 'title':'four'}, ]
    s = sum([i['value'] for i in d])

In PHP I would have done this (I guess)


    function extract_value($r) {
        return $r['value'];
    }
    $d = array(array('value'=>1, 'title'=>'one'), array('value'=>2),
               array('value'=>3), array('value'=>4, 'title'=>'four'));
    $s = array_sum(array_map("extract_value", $d));

Cracks come forward and shorten it please (in any language!).

28 Comments »

  1. Paul said,

    February 14, 2008 at 7:13 pm

    Hmm

    $d = array(array(’value’=>1, ‘title’=>’one’), array(’value’=>2),
    array(’value’=>3), array(’value’=>4, ‘title’=>’four’));

    $s = 0;
    foreach($d as $i) $s += $i['value'];

    seems far simpler :}

  2. Paul said,

    February 14, 2008 at 7:23 pm

    (For those who didn’t know (like me), in PHP :

    NULL + 1 = 1

    then

    $s = 0;
    foreach($d as $i) $s += $i[’value’];

    and

    foreach($d as $i) $s += $i[’value’];

    seem to give the same result, with no warnings/errors. Except if $d is an empty array I guess, since NULL !== 0)

  3. toidinamai said,

    February 14, 2008 at 7:25 pm

    You can remove the brackets from the sum to make it a generator expression instead of a list comprehension: sum(i['value'] for i in d)

  4. Wolfram said,

    February 14, 2008 at 7:52 pm

    Paul, great. that looks far simpler!!!!!! I might should only have put the python piece of code/cake here and said how amazed I am always again.

  5. Pete said,

    February 14, 2008 at 7:56 pm

    The sum function takes an iterator, so use a generator comprehension instead of the list comprehension. All you do is get rid of the brackets. This way there won’t be an extra list copy of all the values.

    s = sum(i['value'] for i in d)

  6. Rich Cavanaugh said,

    February 14, 2008 at 8:06 pm

    Thought I’d chime in with a bit of Ruby:

    d = [{:value => 1, :title => "one"}, {:value => 2}, {:value => 3}, {:value => 4, :title => "four"}]

    s = d.inject(0) {|total, entry| total+entry[:value]}

  7. Popcorn Mariachi said,

    February 14, 2008 at 8:09 pm

    $s = array_sum(array_map(create_function(’$a’, ‘return $a["value"]‘), $d));

  8. Popcorn Mariachi said,

    February 14, 2008 at 8:10 pm

    $s = array_sum(array_map(create_function(’$a’, ‘return $a["value"]‘), $d));

    My local PHP geek always makes me cringe when he uses create_function.
    (I’m a Python geek)

  9. Popcorn Mariachi said,

    February 14, 2008 at 8:10 pm

    Sorry, didn’t mean to doublepost.

  10. Daniel Skinner said,

    February 14, 2008 at 8:26 pm

    yeah, create_function is awful!

  11. Sean Coates said,

    February 14, 2008 at 8:58 pm

    Well, depending what you ACTUALLY need, using key-value pairs is actually very powerful in PHP:

    $d = array(1=>’one’,2=>’two’,3=>’three’,4=>’four’);
    $s = array_sum(array_keys($d));

    S

  12. s0enke said,

    February 14, 2008 at 9:01 pm

    What if no one else can read your crypto-code anymore because you coded it “so cool”. Remember: “Cool code” isn’t always good code.

  13. Pierre said,

    February 14, 2008 at 10:09 pm

    HI Wolfram!

    Using a function is not going to be faster (this function will be called on each iteration), even if it may look smaller :)

  14. Andrew Burton said,

    February 14, 2008 at 10:23 pm

    In Perl (with strict):

    my $s = 0;
    my @d = ({’one’, 1}, {”, 2}, {”, 3}, {’four’, 4});
    map { my @y = values(%{$_}); $s = $s + $y[0]; } @d;

  15. Andrew Burton said,

    February 14, 2008 at 10:28 pm

    Sorry! I thought “type” and “value” were Python specific indicators, not just hash keys. Here:

    my @d = ({’title’,'one’, ‘value’,1}, {’value’, 2}, {’value’, 3}, {’title’,'four’, ‘value’,4});
    my $s = 0; map { $s = $s + $_->{value}; } @d;

  16. marrtins said,

    February 14, 2008 at 11:45 pm

    Here is erlang code:

    -record(datatype, {
    value = 0,
    title = “untitled”
    }).

    sum([H|T]) -> H#datatype.value + sum(T);
    sum([]) -> 0.

    Call it:
    D = [#datatype{value=1, title="one"}, #datatype{value=2}, #datatype{value=3}, #datatype{value=4, title="four"}],
    S=sum(D).

  17. Wolfram said,

    February 14, 2008 at 11:47 pm

    Well I realize that this is no real nut to crack … i was just so overhauled by the simplicity and straight-forwardness how to solve this in python that I had to put this on my blog.
    But I realize that all the latest scripting languages can do it in a alike short manner. Though Python and PHP have the nicest syntax imho. Paul’s PHP approach using the foreach is pretty well readable too!
    Thx for the input

  18. Bruce Weirdan said,

    February 15, 2008 at 12:24 am

    Here’s a shorter “functional programming” version (in php):
    $sum = array_reduce($d, create_function(’$a, $b’, ‘return $a["value"] + $b["value"];’));

    although I would use foreach in this case.

  19. Code Metaphor — Phunctional도 좋아요 said,

    February 15, 2008 at 2:30 am

    [...] Python is steel awesome이라는 글을 보고 생각나서 적습니다. [...]

  20. Shane O'Sullivan said,

    February 15, 2008 at 3:07 pm

    How about some functional programming with JavaScript with Dojo?

    var values = [{'value':1, 'title':'one'}, {'value':2}, {'value':3},{'value':4, 'title':'four'}];
    var sum = dojox.lang.functional.reduce(values, “{value:a['value']+b['value']}”).value;

  21. Mark Thomas said,

    February 15, 2008 at 7:52 pm

    In Ruby on Rails:

    s = d.collect{|item| item[:value]}.sum

    Of course in Ruby it’s just as easy (and much cleaner IMHO) to create real objects instead of arrays-of-arrays-of-hashes, etc. in which case you would do:

    s = d.collect(&:value).sum

    Very readable.

  22. Simon Harrer said,

    February 16, 2008 at 3:00 am

    name l = foldr1 (+) (map (\(a,b) -> b) l)

    this is the solution in haskell. is also very short. first a list of only the second part of the pair is created and then the elements of the list are added by the (+) function.

    how to use the function:
    name [("one",1),("",2),("",3),("",4)]
    result: 10

  23. Simon Harrer said,

    February 16, 2008 at 3:03 am

    reduced to: name l = foldr1 (+) (map snd l)

  24. Language comparisons are always flawed — Quick off the Mark said,

    February 16, 2008 at 6:48 am

    [...] example is a post “Python is still awesome” where problem X is “Given a list of dictionaries, sum the values of one of the dictionary [...]

  25. random_p said,

    February 17, 2008 at 12:28 am

    The original example didn’t make a whole lot of sense. It could have been simply:

    d = {1:’one’, 2:”, 3:”, 4:’four’}
    s = sum(d)

    or if you needed multiple attributes per item:

    d={1:{’title’:'one’, ‘foo’:'bar’}, 2:{}, 3:{}, 4:{’title’:'two’}}
    s = sum{d)

  26. Spacebat said,

    February 17, 2008 at 4:32 am

    Perl without strict mode:
    @d=({value=>1, title=>”one”}, {value=>2}, {value=>3}, {value=>4, title=>”four”});
    $s+=$_->{value} for @d;

  27. galacticsurfer said,

    June 17, 2010 at 4:16 pm

    lol a bit late now i gues but heres my approach

    d = [{'value':1, 'title':'one'}, {'value':2}, {'value':3},
    {'value':4, 'title':'four'}, ]

    for i in d:
    s+=i['value']

  28. w1sh said,

    September 14, 2010 at 10:58 pm

    In calculator it’s:
    1+2+3+4

    Beat that.

RSS feed for comments on this post · TrackBack URL

Leave a Comment