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
    \$\begingroup\$ Suggested test case: [1, 1, 1, 2, 2] , so that one element is repeated more than once \$\endgroup\$ – Luis Mendo Jun 6 '18 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 Jun 6 '18 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 Jun 6 '18 at 13:18
  • 6
    \$\begingroup\$ "standard equality function" seems hard to define, and will probably lead to different results in different languages. \$\endgroup\$ – ngm Jun 6 '18 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 Jun 6 '18 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\$
  • 1
    \$\begingroup\$ Wow! That output really takes you through the stages of the process. \$\endgroup\$ – AJFaraday Jun 6 '18 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\$ – Kaldo Jun 6 '18 at 11:36
  • \$\begingroup\$ I'm beginning to understand how you could actually learn such a language ;) \$\endgroup\$ – AJFaraday Jun 6 '18 at 11:37
  • \$\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\$ – Kevin Cruijssen Jun 6 '18 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\$ – Kaldo Jun 7 '18 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\$
  • \$\begingroup\$ Nice, it's simpler than mine! \$\endgroup\$ – LocustHorde Jun 6 '18 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\$
  • \$\begingroup\$ function(x)x[duplicated(x)] ? \$\endgroup\$ – JayCe Jun 6 '18 at 20:23
  • \$\begingroup\$ @JayCe OK, so yours is shorter, idiomatic, and actually works. But where's your three paragraph essay? \$\endgroup\$ – ngm Jun 6 '18 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 Jun 6 '18 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\$
  • \$\begingroup\$ actually, using the third output of u might work, trying that approach now. \$\endgroup\$ – Giuseppe Jun 6 '18 at 13:22
  • \$\begingroup\$ ugh never mind, u only works for arrays or cell arrays of strings :-( \$\endgroup\$ – Giuseppe Jun 6 '18 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 Jun 7 '18 at 22:03
  • \$\begingroup\$ Nice approach! This should work, 1 byte fewer: "GX@&)m?6Mvu \$\endgroup\$ – Luis Mendo Jun 7 '18 at 22:05
  • \$\begingroup\$ @LuisMendo ah, didn't know X@ worked like that! \$\endgroup\$ – Giuseppe Jun 8 '18 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\$
  • \$\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 Jun 6 '18 at 11:51
  • \$\begingroup\$ @Mr.Xcoder, thanks, will do, I was following the python / etc answers above. \$\endgroup\$ – LocustHorde Jun 6 '18 at 11:53
  • \$\begingroup\$ Check this ltio link \$\endgroup\$ – Luis felipe De jesus Munoz Jun 6 '18 at 12:03
  • \$\begingroup\$ @LuisfelipeDejesusMunoz, of course! thanks. \$\endgroup\$ – LocustHorde Jun 6 '18 at 12:06
  • 1
    \$\begingroup\$ @mazzy, good point, fixed :o \$\endgroup\$ – LocustHorde Jun 6 '18 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\$
  • 1
    \$\begingroup\$ 32 bytes Try it online! \$\endgroup\$ – AdmBorkBork Jun 6 '18 at 12:45
  • \$\begingroup\$ Welcome to PPCG! Nice to see another PowerSheller around. \$\endgroup\$ – AdmBorkBork Jun 6 '18 at 12:46
  • \$\begingroup\$ Thanks, @AdmBorkBork. I cannt open Try it online link. can you post code in comment? \$\endgroup\$ – mazzy Jun 6 '18 at 12:53
  • 1
    \$\begingroup\$ ($args|group|?{$_.count-1}).Name \$\endgroup\$ – AdmBorkBork Jun 6 '18 at 12:57
  • \$\begingroup\$ If you have some problems with TIO you can report in talk.tryitonline.net . \$\endgroup\$ – user202729 Jun 6 '18 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\$
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\$

Retina, 23 bytes

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

Try it online! Explanation:

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

List duplicated lines.

D`

Deduplicate that list.

\$\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\$

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