7
\$\begingroup\$

So, I have an array

['a', 42, 'b', 42, 'a']

I want to alert users to the fact that 42 and 'a' appear in it twice.

some_function(['a', 42, 'b', 42, 'a'])

should return

['a', 42]

Write some code to extract the duplicates from an array.

  • It should accept an array as input.
  • The array can have multiple types of object.
  • Duplication should be defined as per the language's standard equality function (examples are from ruby).
  • It outputs an array of the duplicated items.
  • The order of the returned items is irrelevant.
  • Duplicates should only appear in the returned array once.
  • Golf rules, do it in the smallest number of bytes.

Test cases

[1,2,3] => []

[1,2,3,2,1] => [1,2]

[1.0, 2, 2.0, 1.0] => [1, 2] or [1.0, 2.0] or [1, 2.0] or [1.0, 2]

[1, '1', '1.0'] => []

[nil, nil, false, false, true, true] => [nil, false, true]
\$\endgroup\$
8
  • 8
    \$\begingroup\$ Suggested test case: [1, 1, 1, 2, 2] , so that one element is repeated more than once \$\endgroup\$
    – Luis Mendo
    Commented Jun 6, 2018 at 11:40
  • 5
    \$\begingroup\$ "The array can have multiple types of object." Is this intended to exclude languages that do not allow arrays to have more than one type of object? \$\endgroup\$
    – ngm
    Commented Jun 6, 2018 at 13:05
  • 2
    \$\begingroup\$ [1.0, 2, 2.0, 1.0] could be interpreted as having only one duplicate: 1.0, if one considers the integer 2 and which might be a non-integer 2.0 to be not equal. Since this is intended to allow for different types. \$\endgroup\$
    – ngm
    Commented Jun 6, 2018 at 13:18
  • 6
    \$\begingroup\$ "standard equality function" seems hard to define, and will probably lead to different results in different languages. \$\endgroup\$
    – ngm
    Commented Jun 6, 2018 at 13:20
  • 1
    \$\begingroup\$ Some languages have more than one equality function (for example: Java have Object.equals and ==, JS have === and ==, Python have == and is, and it's 100% opinion-based which one is more "standard"). \$\endgroup\$
    – user202729
    Commented Jun 6, 2018 at 14:09

22 Answers 22

4
\$\begingroup\$

Brachylog, 9 bytes

ọ{tℕ₂&h}ˢ

Try it online!

Explanation

ọ           Occurrences
 {     }ˢ   Select:
     &h       The elements…
  tℕ₂         …which occur at least 2 times
\$\endgroup\$
4
\$\begingroup\$

05AB1E, 8 bytes

{γʒg≠}€н

Try it online!

Explanation

{γ       # Sort input and split into chunks of identical elements
  ʒg≠}   # Keeps chunks of length != 1
      €н # Map with the first element of each chunk
\$\endgroup\$
6
  • 1
    \$\begingroup\$ Wow! That output really takes you through the stages of the process. \$\endgroup\$
    – AJFaraday
    Commented Jun 6, 2018 at 11:35
  • 1
    \$\begingroup\$ @AJFaraday I left the -d argument by accident but it's an amazing tool to understand what happens on the stack when you're learning 05AB1E :-) \$\endgroup\$ Commented Jun 6, 2018 at 11:36
  • \$\begingroup\$ I'm beginning to understand how you could actually learn such a language ;) \$\endgroup\$
    – AJFaraday
    Commented Jun 6, 2018 at 11:37
  • 1
    \$\begingroup\$ Not sure if it's a valid output format with the empty item present, but 6 bytes. Maybe you see something to golf or pretty-print it and still save bytes? \$\endgroup\$ Commented Jun 6, 2018 at 15:02
  • 1
    \$\begingroup\$ @KevinCruijssen That's an interesting take. I'm not quite sure it's a valid output (none of the other answers are leaving empty items in the array). You could add õK at the end to remove those empty arrays (only solution AFAIK to remove empty items from an array) but you'd end up at 8 bytes as well. \$\endgroup\$ Commented Jun 7, 2018 at 7:37
4
\$\begingroup\$

Pyth, 5 bytes

{.-Q{

Try it here!

How it works?

{.-Q{ – Full program.
    { – Deduplicate.
 .-Q  – And apply bagwise subtraction between the input Q and the above.
{     – Deduplicate the result.
\$\endgroup\$
4
\$\begingroup\$

Python 2, 39 38 bytes

lambda l:{v for v in l if~-l.count(v)}

Try it online!


Python 3, 37 bytes

lambda l:[*map(l.remove,{*l})]and{*l}

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Javascript ES6, 48 bytes

a=>[...new Set(a.filter((b,c)=>a.indexOf(b)<c))]

Test cases

f=
a=>[...new Set(a.filter((b,c)=>a.indexOf(b)<c))];

tests=[
    [1,2,3],
    [1,2,3,2,1],
    [1.0, 2, 2.0, 1.0],
    [1, '1', '1.0'],
    [undefined, undefined, false, false, true, true],
    [1,2,1,1,1,2,1,2,2,1,1]
]
console.log(tests.map(b=>f(b)))

\$\endgroup\$
1
  • \$\begingroup\$ Nice, it's simpler than mine! \$\endgroup\$ Commented Jun 6, 2018 at 13:48
3
\$\begingroup\$

[R], 58 bytes

function(x)x[duplicated(x)]

(My original code was nonsense.)

This works with an array input (in R an "atomic vector") but all the elements have to have the same type, or will be coerced to the most general type.

This also works with a list input (the only way in R an "array"-ish object can have elements of different types) which is what the challenge seems to want. The list elements can be other lists, atomic vectors, matrices, data frames - anything, really.

But then the "equality" function used by duplicated is fairly strict and won't give the same answers as the challenge test cases indicate, which is a flaw in the challenge specs and not this answer.

\$\endgroup\$
3
  • \$\begingroup\$ function(x)x[duplicated(x)] ? \$\endgroup\$
    – JayCe
    Commented Jun 6, 2018 at 20:23
  • \$\begingroup\$ @JayCe OK, so yours is shorter, idiomatic, and actually works. But where's your three paragraph essay? \$\endgroup\$
    – ngm
    Commented Jun 6, 2018 at 20:39
  • \$\begingroup\$ ahah ! Don't be too hard on yourself :) I agree with your comment on the "equality" definition and I wouldn't have thought of testing this on lists. \$\endgroup\$
    – JayCe
    Commented Jun 6, 2018 at 21:41
3
\$\begingroup\$

MATL, 13 12 bytes

"GX@&)m?6Mvu

Try it online!

Thanks to Luis Mendo for saving a byte!

using m is the only way I could use mixed-type equality checking. Takes input as a row cell array.

		% (implicit input x)
"		% for loop:
GX@&)		% push input and index, then get x(i) and x(-i),
                % where x(-i) means "x excluding element at index i"
    m		% ismember -- true if x(i) is in x(-i)
     ?		% if true
      6M	% get x(i)
	v	% concatenate with prior results
	 u	% and take unique values
		% implicit end of if
		% implicit end of for loop
		% implicit end of program, output results as cell array
\$\endgroup\$
6
  • \$\begingroup\$ actually, using the third output of u might work, trying that approach now. \$\endgroup\$
    – Giuseppe
    Commented Jun 6, 2018 at 13:22
  • \$\begingroup\$ ugh never mind, u only works for arrays or cell arrays of strings :-( \$\endgroup\$
    – Giuseppe
    Commented Jun 6, 2018 at 13:24
  • \$\begingroup\$ I should work for mixed char-numeric content, but there's a bug. It will corrected in the next release \$\endgroup\$
    – Luis Mendo
    Commented Jun 7, 2018 at 22:03
  • \$\begingroup\$ Nice approach! This should work, 1 byte fewer: "GX@&)m?6Mvu \$\endgroup\$
    – Luis Mendo
    Commented Jun 7, 2018 at 22:05
  • \$\begingroup\$ @LuisMendo ah, didn't know X@ worked like that! \$\endgroup\$
    – Giuseppe
    Commented Jun 8, 2018 at 13:44
2
\$\begingroup\$

Jelly, 4 bytes

œ-QQ

Try it online!

The last test case ([None, None, False, False, True, True]) isn't possible in Jelly.

\$\endgroup\$
2
\$\begingroup\$

PHP, 75 bytes

function a($b){return array_unique(array_diff_assoc($b,array_unique($b)));}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Javascript (ES6), 51 bytes

a=>[...new Set(a.sort().filter((v,i)=>v===a[i+1]))]

run on tio.

Try it:

a=a=>[...new Set(a.sort().filter((v,i)=>v===a[i+1]))]


console.log(a([1,2,3]));
console.log(a([1,2,3,2,1]));
console.log(a([1.0, 2, 2.0, 1.0]));
console.log(a([1, '1', '1.0']));
console.log(a([null, null, false, false, true, true]));
console.log(a([1,1,1,3,2,3,2,3,4]));

\$\endgroup\$
7
  • \$\begingroup\$ On PPCG, submission have to either be functions or programs, but not snippets, unless specifies otherwise. Currently, your answer is a snippet, but you can easily fix that by appending a=> to your code, therefore making it a function. Other than that, nice first answer! Welcome to PPCG! \$\endgroup\$
    – Mr. Xcoder
    Commented Jun 6, 2018 at 11:51
  • \$\begingroup\$ @Mr.Xcoder, thanks, will do, I was following the python / etc answers above. \$\endgroup\$ Commented Jun 6, 2018 at 11:53
  • \$\begingroup\$ Check this ltio link \$\endgroup\$ Commented Jun 6, 2018 at 12:03
  • \$\begingroup\$ @LuisfelipeDejesusMunoz, of course! thanks. \$\endgroup\$ Commented Jun 6, 2018 at 12:06
  • 1
    \$\begingroup\$ @mazzy, good point, fixed :o \$\endgroup\$ Commented Jun 6, 2018 at 12:21
2
\$\begingroup\$

Powershell, 38 32 bytes

($args|group|?{$_.count-1}).Name

Try it online, thanks AdmBorkBork

using:

  1. save the code to a file get-duplicates.ps1
  2. run .\get-duplicates.ps1 'a' 42 'b' 42 'a' 42

Known issues: Powershell supress $null value. Result of

 .\get-duplicates.ps1 $null $null $false $false $true $true

is False, True without null.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ 32 bytes Try it online! \$\endgroup\$ Commented Jun 6, 2018 at 12:45
  • \$\begingroup\$ Welcome to PPCG! Nice to see another PowerSheller around. \$\endgroup\$ Commented Jun 6, 2018 at 12:46
  • \$\begingroup\$ Thanks, @AdmBorkBork. I cannt open Try it online link. can you post code in comment? \$\endgroup\$
    – mazzy
    Commented Jun 6, 2018 at 12:53
  • 1
    \$\begingroup\$ ($args|group|?{$_.count-1}).Name \$\endgroup\$ Commented Jun 6, 2018 at 12:57
  • \$\begingroup\$ If you have some problems with TIO you can report in talk.tryitonline.net . \$\endgroup\$
    – user202729
    Commented Jun 6, 2018 at 14:11
2
\$\begingroup\$

Java (JDK 10), 77 bytes

l->{java.util.Set.copyOf(l).forEach(l::remove);return l.stream().distinct();}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Crystal, 42 bytes

def f(a)a.reject{|x|a.count(x)<2}.uniq
end

Try it online!

Sometimes, when you can't get the desired results, the problem can be solved... by running your code in a different language.

Initially, I tried solving this in Ruby, but ironically, despite the OP's statement that all test cases correspond to Ruby comparison rules, the above code when run in Ruby actually fails for the third test case, as both uniq and array intersection operator use stricter equality checks. However, it passes all tests in Crystal (which shares most of its syntax with Ruby) at the expense of having to declare it as a defined function (-> proc would be longer in Crystal).

As a bonus, here is the golfier Ruby-only version of the code (doesn't pass test 3):

Ruby, 33 bytes

->a{a.reject{|x|a.count(x)<2}|[]}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Japt -h, 7 bytes

â £kX â

Try it online!

Explanation:

â £kX â
â         // Get all unique items from the input
  £       // Map X through the results
   kX     //   Remove X from the input
      â   //   Get unique items
-h        // Return the last item
\$\endgroup\$
0
1
\$\begingroup\$

Gaia, 4 bytes

:uDu

Try it online!

: duplicates the input, u uniquifies it, D retrieves the multiset difference between the two and u uniquifies the result.

\$\endgroup\$
1
\$\begingroup\$

Husk, 4 bytes

uṠ-u

Try it online!

Explanation

     -- input, e.g. [2,1,1,3,2,2]
   u -- remove duplicates: [2,1,3]
 Ṡ-  -- subtract this from original list: [2,1,1,3,2,2] - [2,1,3] = [1,2,2]
u    -- remove duplicates: [1,2]
\$\endgroup\$
1
\$\begingroup\$

Physica, 33 bytes

->a:Set@Filter[->e:a.count@e>1;a]

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Haskell, 33 bytes

nub.((\\)<*>nub)
import Data.List

Try it online! Port of my Husk answer.

The point-free version given above is equivalent to f x=nub$x\\nub x which is one byte longer.


Haskell, 50 bytes

([]#)
a#(x:r)=([x|any(==x)r,all(/=x)a]++a)#r
a#_=a

Try it online! Alternative without imports.

\$\endgroup\$
1
\$\begingroup\$

Proton, 32 bytes

l=>set(v for v:l if~-l.count(v))

Try it online!

Port of TFeld's Python answer. Could be shorter but {...} apparently doesn't work for setcomps.

\$\endgroup\$
1
\$\begingroup\$

Red, 46 bytes

func[b][foreach c unique b[alter b c]unique b]

Doesn't work for numbers in different representation as float or string.

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Stax, 5 bytes

═H+U(

Run and debug it

Explanation:

cu|-uJ Full program, unpacked
cu     Copy and make unique
  |-   Remove each element once
    u  Make unique again
     J Join by space. 'm' would be equally long, but as F has a lower charcode, it can be packed better.
\$\endgroup\$
1
\$\begingroup\$

Retina, 23 22 bytes

Lmsl`(.+)(?=.+^\1$)
D`

Try it online! Explanation:

Lmsl`(.+)(?=.+^\1$)

List duplicated lines. The m modifier allows the ^ and $ to match the start and end of a line in the lookahead. The s modifier allows us to look ahead past newlines using just .+. The l modifier automatically anchors the match to whole lines. I can't use the p flag though as the match could be more than one line at once, however the next stage will deal with that.

D`

Deduplicate that list.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.