Find unique elements based on a given key

8

Input

Take a list of values xi each paired with a key yi.

[(x1, y1), (x2, y2), ...]

Output

Return a list L containing only values from the set {xi}.

  • The length of L must be equal to the number of unique keys k in the set {yi}.
  • For each unique key k there must be a value from {xi} that has key k.

Details

  • Standard loopholes disallowed.
  • You can assume all values in the input will be nonnegative integers.
  • There may be duplicate values and keys.
  • You can assume there is at least one value/key pair in the input.
  • If you prefer to take two lists of equal length as input (one for values, one for keys) that is fine.
  • You may not take any other input.
  • The order of the list you output does not matter.
  • The xi you choose for each key does not matter.

For example, with input [[0, 0], [1, 3], [2, 3]] you can return either [0, 1] or [0, 2] or any permutation of these.

Examples

[[1, 2], [3, 2], [3, 0]]  -> [1, 3] or [3, 3]
[[7, 2], [7, 0], [7, 1]]  -> [7, 7, 7]
[[4, 0], [4, 0], [9, 1], [5, 2]]  -> [4, 9, 5]
[[9, 1], [99, 10], [5, 5], [0, 3]]  -> [9, 99, 5, 0]

Fewest bytes wins.

dylnan

Posted 2018-06-06T14:47:30.923

Reputation: 4 993

Can I take input in the form key value key value key value ...? – wastl – 2018-06-06T15:10:42.773

@wastl Yes you can – dylnan – 2018-06-06T15:15:12.147

What if your language doesn't support Maps containing the same keys? Can we take two arrays as keys and values as input? Or create our own custom Map that does take multiple values as input (or perhaps a list of key-value pairs)? – Kevin Cruijssen – 2018-06-06T15:15:23.670

1@KevinCruijssen If you prefer to take two lists of equal length as input that is fine. Is this what you mean? I don't know what you mean about "Maps". – dylnan – 2018-06-06T15:17:45.717

@dylnan Ah, that was indeed what I meant, thanks. Read past it. And "maps" is the term for key-value pairs in Java, not sure if it's called differently in other languages. – Kevin Cruijssen – 2018-06-06T15:19:02.163

@KevinCruijssen "maps" is how I learnt it, some languages like Perl call them hashes (short for hash maps I guess), and the currently popular term seems to be dictionaries or dicts. – sundar - Reinstate Monica – 2018-06-06T21:28:33.140

Answers

4

Python 2, 34 bytes

lambda a,b:dict(zip(b,a)).values()

Try it online!

Takes input as list of values and list of keys.
Generate dictionary, swapping keys and values, which leaves only unique y values. Return all corresponding x values

Dead Possum

Posted 2018-06-06T14:47:30.923

Reputation: 3 256

1

You can save 3 bytes if you reverse the order of the input arguments (the question doesn't prescribe a specific order) and take and pass them as variadic arguments: https://tio.run/##K6gsycjPM/qfYxvzPycxNyklUSvRKiUzuUSjKrNAQytRU1OvLDGnNLVYQ/N/QVFmXolCjka0kY4CEBnE6ihEG@ooGANRrCYXXNZQx9BAx1THGCRtqWNpCWQbxGr@BwA

– David Foerster – 2018-06-07T00:03:35.427

4

Jelly, 2 bytes

Ḣƙ

Try it online!

Takes two lists of equal length, first is keys, second is values.

Erik the Outgolfer

Posted 2018-06-06T14:47:30.923

Reputation: 38 134

4

J, 4 bytes

{./.

How?

The left argument x is a list of key, the right one y- a list of values

/. groups y according x

{. takes the first element of each group

Try it online!

Galen Ivanov

Posted 2018-06-06T14:47:30.923

Reputation: 13 815

3

Clojure, 20 18 bytes

(comp vals zipmap)

This takes lists of values and keys as arguments, in that order.

NikoNyrh

Posted 2018-06-06T14:47:30.923

Reputation: 2 361

2

Stax, 5 bytes

╠HB%§

Run and debug it

Takes two arrays, first values, then keys.

Explanation:

cu:I@J Full program, unpacked
cu     Push a unique copy of the keys.
  :I   Indices of the unique elements
    @  Index the values array
     J Join by space
       Implicit output

wastl

Posted 2018-06-06T14:47:30.923

Reputation: 3 089

2

Python 3, 42 bytes

lambda a,b:[dict(zip(b,a))[q]for q in{*b}]

Try it online!

a = values
b = keys

HyperNeutrino

Posted 2018-06-06T14:47:30.923

Reputation: 26 575

2

JavaScript (ES8), 43 bytes

Takes input as 2 distinct lists in currying syntax (values)(keys).

v=>k=>v.filter(o=(x,i)=>o[j=k[i]]?0:o[j]=1)

Try it online!

Arnauld

Posted 2018-06-06T14:47:30.923

Reputation: 111 334

Today's JavaScript lesson: functions are arrays. – Jakob – 2018-06-06T23:46:13.017

@Jakob More precisely, functions are objects. At the end of the first test case, o looks like { [Function: o] '0': 1, '2': 1 }. – Arnauld – 2018-06-07T05:55:18.223

2

Haskell, 49 47 bytes

map fst.nubBy((.snd).(==).snd)
import Data.List

Try it online! Input as a list of tuples, e.g. [(1, 2), (3, 2), (3, 0)].


Input as list of lists (49 bytes)

map(!!0).nubBy(\a b->a!!1==b!!1)
import Data.List

Try it online!

Laikoni

Posted 2018-06-06T14:47:30.923

Reputation: 23 676

2

Husk, 4 bytes

ṁhüt

Try it online!

How?

ṁhüt – Full program. 
  üt – Group by tail (the lists without the first element).
ṁh   – Map heads (the lists without the last element) and concatenate the results.

Mr. Xcoder

Posted 2018-06-06T14:47:30.923

Reputation: 39 774

2

R, 30 bytes

function(x,y)x[!duplicated(y)]

Try it online!

ngm

Posted 2018-06-06T14:47:30.923

Reputation: 3 974

2

Japt, 8 bytes

â £VgUbX

Japt Interpreter

Thanks to Shaggy for saving 1 last byte

Completely reworked the logic. Takes some cues from Luis' answer, but I think it's still improved. Now takes input as two lists, keys, values. Apparently I'm still short of optimal though.

Explanation:

â £         For each unique Key X
     Ub     find the first index in "keys"
       X    which is equal to X
   Vg       then take the "value" with the same index

Kamil Drakari

Posted 2018-06-06T14:47:30.923

Reputation: 3 461

12 bytes. You might be able to save a few bytes by taking the keys & values as separate inputs. – Shaggy – 2018-07-06T06:34:32.870

There is an 8 byte solution if you want to try for it. – Shaggy – 2018-07-06T07:38:19.183

The ¥ isn't needed ;) – Shaggy – 2018-07-06T14:15:02.433

@Shaggy Indeed! I had been wondering what the difference between the overloads of b were, didn't notice at all that only one of them took a function. – Kamil Drakari – 2018-07-06T14:18:02.803

And that's the 8 solution I had in mind now, nicely done. Incidendtally, you could reverse the inputs and it would still be 8 bytes: Vâ £gVbX. – Shaggy – 2018-07-06T14:24:32.867

1

Ruby, 27 bytes

->a,b{b.zip(a).to_h.values}

Try it online!

Takes input as two arrays (the footer transforms the original test cases into this format).

Kirill L.

Posted 2018-06-06T14:47:30.923

Reputation: 6 693

1

05AB1E, 4 bytes

DÙkè

Take two input lists: first the values, then the keys.

Try it online or verify all test cases.

Explanation:

D        # Duplicate the values-list
 Ù       # Get all unique items of the values-list
         #  i.e. [0,0,1,0,2] → ['0','1','2']
  k      # Get all (first) indices of these unique values
         #  i.e. [0,0,1,0,2] and ['0','1','2'] → [0,2,4]
   è     # And use this index to get the key from the keys-list
         #  i.e. [0,2,4] and [4,4,9,5,4] → [4,9,4]

Kevin Cruijssen

Posted 2018-06-06T14:47:30.923

Reputation: 67 575

1

Julia 0.6, 36 34 32 bytes

A->values(Dict(y=>x for(x,y)=A))

Try it online!

(shaved off two bytes thanks to @JonathanFrech)
(another two bytes by replacing with = in comprehension)

The input format specified in the question [[1, 2], [2, 7]] works as it is in Julia as an array of arrays containing (potential) key value pairs, the only thing to take care of is that the key comes second and value first.


Slight change, for the same bytecount,

A->values(Dict((y,x)for(x,y)∈A))

Try it online!

sundar - Reinstate Monica

Posted 2018-06-06T14:47:30.923

Reputation: 5 296

Welcome to PPCG! I am in no way familiar with Julia, but it seems to me you may be able to shave off two bytes by removing both square brackets. – Jonathan Frech – 2018-06-06T21:40:22.223

Thank you. I had assumed the brackets were always necessary for comprehensions, but seems they're optional when they're used as an argument. Good suggestion, especially for a non-Julia user! :) – sundar - Reinstate Monica – 2018-06-06T21:57:50.437

1I am assuming it is some sort of tuple comprehension (coming from Python). As a general tip, TIO has a copy wizard which allows you to easily compose a PPCG submission (link icon in the upper right corner, circumvents problems like the leading space in your current post). With small golfs like mine it is not absolutely necessary, but generally I would advise to credit golfing improvements from other users. – Jonathan Frech – 2018-06-06T22:15:34.730

Ah, I was just wondering how everyone's submissions were in a uniform format, whether there was some automation tool I didn't know about. I was using the link icon, but lazily stopped scrolling at the Markdown one, and didn't realize there was one specifically for PPCG. (And noted about the crediting part, will do.) – sundar - Reinstate Monica – 2018-06-06T22:23:06.723

1

Julia 0.6, 29 26 19 bytes

values∘Dict∘zip

Try it online!

Point-free style. Takes input as an array of keys and an array of values.


Older solution:

29 26 bytes

v\k=values(Dict(zip(k,v)))

Try it online!

-3 bytes using operator syntax instead of lambda

Takes input as an array of values and an array of keys.

sundar - Reinstate Monica

Posted 2018-06-06T14:47:30.923

Reputation: 5 296

1

Java 8, 82 bytes

A lambda from a stream of int[] pairs to java.util.Collection<Integer>.

m->m.collect(java.util.stream.Collectors.toMap(a->a[1],a->a[0],(a,b)->a)).values()

Try It Online

Jakob

Posted 2018-06-06T14:47:30.923

Reputation: 2 428

1

Japt, 24 20 16 8 bytes

-4 bytes thanks to @Shaggy

Takes input as key, values

â £VgUbX

Try it online!


Japt, 20 18 bytes

r@bY <Z?X:XpVgY}[]

Try it online!

Luis felipe De jesus Munoz

Posted 2018-06-06T14:47:30.923

Reputation: 9 639

1A few quick tips/hints to help you golf this further: 1 Reverse the inputs, 2 Check the Unicode shortcuts. – Shaggy – 2018-07-04T15:38:11.993

Thanks @Shaggy I'm still reading all the methods from the docs and d trying to adapt. I'll golf this even more in a couple of hours – Luis felipe De jesus Munoz – 2018-07-04T15:41:33.323

There is an 8 byte solution if you want to try for it. – Shaggy – 2018-07-06T07:38:02.093

Instead of m@A?B:C} k¥B, you may want to try k@A} m@C :-) – ETHproductions – 2018-07-07T16:12:26.570

1

MATL, 9 bytes

viiQ(5Mu)

Try it online!

Probably suboptimal, but hey, it works!

Uses the facts that (a) input is guaranteed to have only non-negative integers, (b) MATL extends an array of you try to assign to an index that doesn't exist.

v - create an empty array in the stack

i - get array of values

iQ - get array of keys, increment by 1 (so the minimum value is 1, not 0, since MATL indexing is 1-based)

( - assignment indexing - use the array of keys as indices and assign the values to those indices (if any keys are repeated, only the last value remains in that location)

5M - gets the last input of the last call - which would be the array of indices we used

u) - take a unique list of those indices, index with that list, and leave that result (which is a list of values of unique keys) in the stack

sundar - Reinstate Monica

Posted 2018-06-06T14:47:30.923

Reputation: 5 296

0

Pyth, 7 bytes

hMhM.ge

All testcases.

Leaky Nun

Posted 2018-06-06T14:47:30.923

Reputation: 45 011

0

Perl 5 -pa, 24 bytes

%a=@F;$_=join$/,values%a

Try it online!

Takes input in the format key value key value key value .... TIO footer is only to separate test cases.

wastl

Posted 2018-06-06T14:47:30.923

Reputation: 3 089

0

Perl 6, 25 bytes

{.unique(:as(*[1]))[*;0]}

Try it

Expanded:

{  # bare block lambda with implicit parameter $_

  .unique(  # find the unique results (implicit method call on $_)

    :as(    # use this code to compare
      *[1]  # the second value (WhateverCode lambda)
    )

  )[        # index into that
    *;      # all in the top level
    0       # only the first value from each
  ]
}

Brad Gilbert b2gills

Posted 2018-06-06T14:47:30.923

Reputation: 12 713

Well done. I'm always shocked by the conciseness of Perl 6. – Jakob – 2018-06-06T23:37:57.123

0

C-Sharp, 63 bytes

object _(int[][]p)=>p.GroupBy(i=>i[1]).Select(g=>g.First()[0]);

Returns an enumerable of integers.

LHHuman

Posted 2018-06-06T14:47:30.923

Reputation: 1

0

Wolfram Language (Mathematica), 25 bytes

#&@@#&@@@#~GatherBy~Last&

Try it online!

alephalpha

Posted 2018-06-06T14:47:30.923

Reputation: 23 988

0

Rust, 81 bytes

|a,b|b.zip(a).collect::<std::collections::HashMap<_,_>>().into_iter().map(|v|v.1)

Try it online!

Takes two iterators, returns an iterator.

Konrad Borowski

Posted 2018-06-06T14:47:30.923

Reputation: 11 185

0

Perl 6, 12 bytes

{%$_.values}

Try it online!

Coerces the given list to a Hash and then returns the values. This works on both a list of pairs, and a list of key, value, key, value....

Jo King

Posted 2018-06-06T14:47:30.923

Reputation: 38 234