Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #102652 > unrolled thread

Set Operations on Dicts

Started byMarco Kaulea <marco.kaulea@gmail.com>
First post2016-02-08 10:56 +0100
Last post2016-02-09 08:14 -0700
Articles 11 — 6 participants

Back to article view | Back to comp.lang.python


Contents

  Set Operations on Dicts Marco Kaulea <marco.kaulea@gmail.com> - 2016-02-08 10:56 +0100
    Re: Set Operations on Dicts Jussi Piitulainen <jussi.piitulainen@helsinki.fi> - 2016-02-08 14:17 +0200
      Re: Set Operations on Dicts Marco Kaulea <marco.kaulea@gmail.com> - 2016-02-08 13:33 +0100
      Re: Set Operations on Dicts Matt Wheeler <m@funkyhat.org> - 2016-02-08 13:32 +0000
        Re: Set Operations on Dicts Jussi Piitulainen <jussi.piitulainen@helsinki.fi> - 2016-02-08 16:02 +0200
      Re: Set Operations on Dicts Random832 <random832@fastmail.com> - 2016-02-08 09:52 -0500
        Re: Set Operations on Dicts Jussi Piitulainen <jussi.piitulainen@helsinki.fi> - 2016-02-08 17:05 +0200
    Re: Set Operations on Dicts Grobu <snailcoder@retrosite.invalid> - 2016-02-08 13:47 +0100
      Re: Set Operations on Dicts Ian Kelly <ian.g.kelly@gmail.com> - 2016-02-08 09:12 -0700
        Re: Set Operations on Dicts Grobu <snailcoder@retrosite.invalid> - 2016-02-09 08:21 +0100
          Re: Set Operations on Dicts Ian Kelly <ian.g.kelly@gmail.com> - 2016-02-09 08:14 -0700

#102652 — Set Operations on Dicts

FromMarco Kaulea <marco.kaulea@gmail.com>
Date2016-02-08 10:56 +0100
SubjectSet Operations on Dicts
Message-ID<mailman.86.1454925476.2317.python-list@python.org>
Hi,

In one talk (I think it was [1]) it was described that sets are basically
dicts without the values.
Therefor it should be easy to apply set operations on dicts, for example:
{'a': 123, 'b': 456} & {'a'} => {'a': 123}
{'a': 123, 'b': 456} - {'a'} => {'b': 456}

This if currently not implemented. Is there a technical reason that this is
difficult or are
there a lot of corner cases that make it not worth the trouble?

I have not spend a lot of time on this, I just needed a feature like that
and was surprised that
it did not exists.

- Marco

[1] https://www.youtube.com/watch?v=C4Kc8xzcA68

[toc] | [next] | [standalone]


#102664

FromJussi Piitulainen <jussi.piitulainen@helsinki.fi>
Date2016-02-08 14:17 +0200
Message-ID<lf5fux3xuov.fsf@ling.helsinki.fi>
In reply to#102652
Marco Kaulea writes:

> In one talk (I think it was [1]) it was described that sets are
> basically dicts without the values.  Therefor it should be easy to
> apply set operations on dicts, for example:
>
> {'a': 123, 'b': 456} & {'a'} => {'a': 123}
> {'a': 123, 'b': 456} - {'a'} => {'b': 456}
>
> This if currently not implemented. Is there a technical reason that
> this is difficult or are there a lot of corner cases that make it not
> worth the trouble?

I think nobody was quite willing to lay down the law on which dictionary
would take precedence when they have keys in common but different values
on those keys. Both ways make sense, and sometimes you want something
like arithmetic done to combine the values on common keys.

(A collection.Counter does some version of the latter, I think. Maybe
the answer is to create a custom class that allows what you want?)

But that's an interesting proposal to only allow sets as the second
argument. Those particular cases may not be *too* difficult to express
as comprehensions, though still quite a mouthful compared to your
suggestion:

{ k:d[k] for k in d if k in s }     # d & s

{ k:d[k] for k in d if k not in s } # d - s

Perhaps there is already some more compact expression for these?

Also, what would be the nicest current way to express a priority union
of dicts?

{ k:(d if k in d else e)[k] for k in d.keys() | e.keys() }

> I have not spend a lot of time on this, I just needed a feature like
> that and was surprised that it did not exists.
>
> - Marco
>
> [1] https://www.youtube.com/watch?v=C4Kc8xzcA68

[toc] | [prev] | [next] | [standalone]


#102667

FromMarco Kaulea <marco.kaulea@gmail.com>
Date2016-02-08 13:33 +0100
Message-ID<mailman.95.1454935075.2317.python-list@python.org>
In reply to#102664
On Mon, Feb 8, 2016 at 1:17 PM, Jussi Piitulainen <
jussi.piitulainen@helsinki.fi> wrote:

> I think nobody was quite willing to lay down the law on which dictionary
> would take precedence when they have keys in common but different values
> on those keys. Both ways make sense, and sometimes you want something
> like arithmetic done to combine the values on common keys.
>
I don't expect this to be really useful. I only thought about using a set
as a second argument.


But that's an interesting proposal to only allow sets as the second
> argument. Those particular cases may not be *too* difficult to express
> as comprehensions, though still quite a mouthful compared to your
> suggestion:
>
That is the restriction I had in mind.

{ k:d[k] for k in d if k in s }     # d & s
>
> { k:d[k] for k in d if k not in s } # d - s
>
> That is basically what I did. But I expect this could be quite slow, since
it has to take
each value in s and perform a lookup in d. I would expect the pure set
implementation
to be more optimized.


Also, what would be the nicest current way to express a priority union
> of dicts?
>
> { k:(d if k in d else e)[k] for k in d.keys() | e.keys() }

This seems like it might be useful for default configurations, as that is
currently
quite the hassle to do with `x = conf.get('x', fallback="default")

[toc] | [prev] | [next] | [standalone]


#102669

FromMatt Wheeler <m@funkyhat.org>
Date2016-02-08 13:32 +0000
Message-ID<mailman.96.1454938384.2317.python-list@python.org>
In reply to#102664
On 8 February 2016 at 12:17, Jussi Piitulainen
<jussi.piitulainen@helsinki.fi> wrote:
> Also, what would be the nicest current way to express a priority union
> of dicts?
>
> { k:(d if k in d else e)[k] for k in d.keys() | e.keys() }

Since Python 3.5: {**e, **d}


-- 
Matt Wheeler
http://funkyh.at

[toc] | [prev] | [next] | [standalone]


#102670

FromJussi Piitulainen <jussi.piitulainen@helsinki.fi>
Date2016-02-08 16:02 +0200
Message-ID<lf5bn7r1erb.fsf@ling.helsinki.fi>
In reply to#102669
Matt Wheeler writes:

> On 8 February 2016 at 12:17, Jussi Piitulainen wrote:
>> Also, what would be the nicest current way to express a priority union
>> of dicts?
>>
>> { k:(d if k in d else e)[k] for k in d.keys() | e.keys() }
>
> Since Python 3.5: {**e, **d}

Thanks. I have considered this news briefly and I think I'll like it :)

[toc] | [prev] | [next] | [standalone]


#102673

FromRandom832 <random832@fastmail.com>
Date2016-02-08 09:52 -0500
Message-ID<mailman.98.1454943165.2317.python-list@python.org>
In reply to#102664
On Mon, Feb 8, 2016, at 08:32, Matt Wheeler wrote:
> On 8 February 2016 at 12:17, Jussi Piitulainen
> <jussi.piitulainen@helsinki.fi> wrote:
> > Also, what would be the nicest current way to express a priority union
> > of dicts?
> >
> > { k:(d if k in d else e)[k] for k in d.keys() | e.keys() }
> 
> Since Python 3.5: {**e, **d}

And before that... dict(ChainMap(d, e))

[toc] | [prev] | [next] | [standalone]


#102675

FromJussi Piitulainen <jussi.piitulainen@helsinki.fi>
Date2016-02-08 17:05 +0200
Message-ID<lf57fif1bu3.fsf@ling.helsinki.fi>
In reply to#102673
Random832 writes:

> On Mon, Feb 8, 2016, at 08:32, Matt Wheeler wrote:
>> On 8 February 2016 at 12:17, Jussi Piitulainen wrote:
>> > Also, what would be the nicest current way to express a priority union
>> > of dicts?
>> >
>> > { k:(d if k in d else e)[k] for k in d.keys() | e.keys() }
>> 
>> Since Python 3.5: {**e, **d}
>
> And before that... dict(ChainMap(d, e))

New in version 3.3. Thanks, I didn't know of that either. Reading the
docs, I think for the use I had in mind, ChainMap(d, e) itself would
suffice.

[toc] | [prev] | [next] | [standalone]


#102668

FromGrobu <snailcoder@retrosite.invalid>
Date2016-02-08 13:47 +0100
Message-ID<n9a2jk$9s$1@dont-email.me>
In reply to#102652
You can use dictionary comprehension :

Say :
dict1 = {'a': 123, 'b': 456}
set1 = {'a'}

intersection :
 >>> { key:dict1[key] for key in dict1 if key in set1 }
{'a': 123}

difference :
 >>> { key:dict1[key] for key in dict1 if not key in set1 }
{'b': 456}

[toc] | [prev] | [next] | [standalone]


#102685

FromIan Kelly <ian.g.kelly@gmail.com>
Date2016-02-08 09:12 -0700
Message-ID<mailman.106.1454948013.2317.python-list@python.org>
In reply to#102668
On Mon, Feb 8, 2016 at 5:47 AM, Grobu <snailcoder@retrosite.invalid> wrote:
> You can use dictionary comprehension :
>
> Say :
> dict1 = {'a': 123, 'b': 456}
> set1 = {'a'}
>
> intersection :
>>>> { key:dict1[key] for key in dict1 if key in set1 }
> {'a': 123}
>
> difference :
>>>> { key:dict1[key] for key in dict1 if not key in set1 }
> {'b': 456}

dict does already expose set-like views. How about:

{k: d[k] for k in d.keys() & s}  # d & s
{k: d[k] for k in d.keys() - s}  # d - s

[toc] | [prev] | [next] | [standalone]


#102706

FromGrobu <snailcoder@retrosite.invalid>
Date2016-02-09 08:21 +0100
Message-ID<n9c3rd$1vt$1@dont-email.me>
In reply to#102685
On 08/02/16 17:12, Ian Kelly wrote:

> dict does already expose set-like views. How about:
>
> {k: d[k] for k in d.keys() & s}  # d & s
> {k: d[k] for k in d.keys() - s}  # d - s
>
Interesting. But seemingly only applies to Python 3.

[toc] | [prev] | [next] | [standalone]


#102728

FromIan Kelly <ian.g.kelly@gmail.com>
Date2016-02-09 08:14 -0700
Message-ID<mailman.10.1455030904.29838.python-list@python.org>
In reply to#102706
On Tue, Feb 9, 2016 at 12:21 AM, Grobu <snailcoder@retrosite.invalid> wrote:
> On 08/02/16 17:12, Ian Kelly wrote:
>
>> dict does already expose set-like views. How about:
>>
>> {k: d[k] for k in d.keys() & s}  # d & s
>> {k: d[k] for k in d.keys() - s}  # d - s
>>
> Interesting. But seemingly only applies to Python 3.

Substitute d.viewkeys() for d.keys() in Python 2.7.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web