Show duplicates in Mathematica - list

In Mathematica I have a list:
x = {1,2,3,3,4,5,5,6}
How will I make a list with the duplicates? Like:
{3,5}
I have been looking at Lists as Sets, if there is something like Except[] for lists, so I could do:
unique = Union[x]
duplicates = MyExcept[x,unique]
(Of course, if the x would have more than two duplicates - say, {1,2,2,2,3,4,4}, there the output would be {2,2,4}, but additional Union[] would solve this.)
But there wasn't anything like that (if I did understand all the functions there well).
So, how to do that?

Lots of ways to do list extraction like this; here's the first thing that came to my mind:
Part[Select[Tally#x, Part[#, 2] > 1 &], All, 1]
Or, more readably in pieces:
Tally#x
Select[%, Part[#, 2] > 1 &]
Part[%, All, 1]
which gives, respectively,
{{1, 1}, {2, 1}, {3, 2}, {4, 1}, {5, 2}, {6, 1}}
{{3, 2}, {5, 2}}
{3, 5}
Perhaps you can think of a more efficient (in time or code space) way :)
By the way, if the list is unsorted then you need run Sort on it first before this will work.

Here's a way to do it in a single pass through the list:
collectDups[l_] := Block[{i}, i[n_]:= (i[n] = n; Unevaluated#Sequence[]); i /# l]
For example:
collectDups[{1, 1, 6, 1, 3, 4, 4, 5, 4, 4, 2, 2}] --> {1, 1, 4, 4, 4, 2}
If you want the list of unique duplicates -- {1, 4, 2} -- then wrap the above in DeleteDuplicates, which is another single pass through the list (Union is less efficient as it also sorts the result).
collectDups[l_] :=
DeleteDuplicates#Block[{i}, i[n_]:= (i[n] = n; Unevaluated#Sequence[]); i /# l]
Will Robertson's solution is probably better just because it's more straightforward, but I think if you wanted to eek out more speed, this should win. But if you cared about that, you wouldn't be programming in Mathematica! :)

Here are several faster variations of the Tally method.
f4 uses "tricks" given by Carl Woll and Oliver Ruebenkoenig on MathGroup.
f2 = Tally## /. {{_, 1} :> Sequence[], {a_, _} :> a} &;
f3 = Pick[#, Unitize[#2 - 1], 1] & ## Transpose#Tally## &;
f4 = # ~Extract~ SparseArray[Unitize[#2 - 1]]["NonzeroPositions"] & ## Transpose#Tally## &;
Speed comparison (f1 included for reference)
a = RandomInteger[100000, 25000];
f1 = Part[Select[Tally##, Part[#, 2] > 1 &], All, 1] &;
First#Timing#Do[##a, {50}] & /# {f1, f2, f3, f4, Tally}
SameQ ## (##a &) /# {f1, f2, f3, f4}
Out[]= {3.188, 1.296, 0.719, 0.375, 0.36}
Out[]= True
It is amazing to me that f4 has almost no overhead relative to a pure Tally!

Using a solution like dreeves, but only returning a single instance of each duplicated element, is a bit on the tricky side. One way of doing it is as follows:
collectDups1[l_] :=
Module[{i, j},
i[n_] := (i[n] := j[n]; Unevaluated#Sequence[]);
j[n_] := (j[n] = Unevaluated#Sequence[]; n);
i /# l];
This doesn't precisely match the output produced by Will Robertson's (IMO superior) solution, because elements will appear in the returned list in the order that it can be determined that they're duplicates. I'm not sure if it really can be done in a single pass, all the ways I can think of involve, in effect, at least two passes, although one might only be over the duplicated elements.

Here is a version of Robertson's answer that uses 100% "postfix notation" for function calls.
identifyDuplicates[list_List, test_:SameQ] :=
list //
Tally[#, test] & //
Select[#, #[[2]] > 1 &] & //
Map[#[[1]] &, #] &
Mathematica's // is similar to the dot for method calls in other languages. For instance, if this were written in C# / LINQ style, it would resemble
list.Tally(test).Where(x => x[2] > 1).Select(x => x[1])
Note that C#'s Where is like MMA's Select, and C#'s Select is like MMA's Map.
EDIT: added optional test function argument, defaulting to SameQ.
EDIT: here is a version that addresses my comment below & reports all the equivalents in a group given a projector function that produces a value such that elements of the list are considered equivalent if the value is equal. This essentially finds equivalence classes longer than a given size:
reportDuplicateClusters[list_List, projector_: (# &),
minimumClusterSize_: 2] :=
GatherBy[list, projector] //
Select[#, Length## >= minimumClusterSize &] &
Here is a sample that checks pairs of integers on their first elements, considering two pairs equivalent if their first elements are equal
reportDuplicateClusters[RandomInteger[10, {10, 2}], #[[1]] &]

This thread seems old, but I've had to solve this myself.
This is kind of crude, but does this do it?
Union[Select[Table[If[tt[[n]] == tt[[n + 1]], tt[[n]], ""], {n, Length[tt] - 1}], IntegerQ]]

Given a list A,
get the non-duplicate values in B
B = DeleteDuplicates[A]
get the duplicate values in C
C = Complement[A,B]
get the non-duplicate values from the duplicate list in D
D = DeleteDuplicates[C]
So for your example:
A = 1, 2, 2, 2, 3, 4, 4
B = 1, 2, 3, 4
C = 2, 2, 4
D = 2, 4
so your answer would be DeleteDuplicates[Complement[x,DeleteDuplicates[x]]] where x is your list. I don't know mathematica, so the syntax may or may not be perfect here. Just going by the docs on the page you linked to.

Another short possibility is
Last /# Select[Gather[x], Length[#] > 1 &]

Related

Elixir: How to find ALL occurrences of a value from a list of tuples?

Find all occurrences of {1, _}; in other words, all first element values that are 1 from each tuple in the list.
Consider the following input:
[
{1, 0},
{2, 2},
{1, 1},
{11, 1},
{1, 3},
{1, 2},
{13, 1}
]
Expected Output:
[{1,0}, {1,1}, {1,3}, {1,2}]
I tried Enum.find(tl(input), fn x -> elem(x, 0) == elem(hd(input), 0) end), but I realized that Enum.find/2 only returns the first and only one element that matches the criteria or function, which is: {1,1}.
My goal is to find all tuples that contain {1, _}, where the first element must be 1 and the second element can be any value.
Here you can use a comprehension with pattern-matching:
result = for x = {1, _} <- list, do: x
Any x that doesn't match the pattern {1, _} will be filtered out.
See the documentation for for/1 for more information.
You could also use Enum.filter/2 together with the match?/2 macro to achieve the same result:
result = Enum.filter(list, fn x -> match?({1, _}, x) end)
Enum.find/2 is useful when you are looking for a single element, e.g. if you want to find the first entry matching your condition.

Replacing successive decreasing numbers by the last number of the sequence in Prolog

I've been trying to solve this problem for quite sometime and I think the logic I'm attempting is flawed.
The objective is to replace a subsequently decreasing sublist of numbers by the last of the sublist.
?- compare([1, 3, 7, 6, 5, 10, 9], Result).
Result = [1, 3, 5, 9] ;
false.
What I tried was:
compare([A,B|T],X):-
%succ(B,A),
A is B+1,
append([],NextX,X),
compare([B|T],NextX).
remove([A,B|T],X):-
A=\=B+1,
compare([B|T],X).
I'm not certain how to write the base case for the compare/2 and I think the I'm not correctly converting my logic into the code. What I'm trying here is to compare A and B and drop A from the list if they are successive numbers.
Your help is very much appreciated.
You are almost there. First cover the special case: If the list contains only one element it is in the list.
compare([X],[X]).
your second rule just needs little altering:
compare([A,B|T],X):- % A is not in the list if
A is B+1, % A = B+1
compare([B|T],X). % Note: X is the same as in head of rule
Your predicate remove/2 is should be the 3rd rule of compare/2 covering the alternative case:
compare([A,B|T],[A|X]):- % A is in the list
A=\=B+1, % if A is not B+1
compare([B|T],X).
Now the query works:
?- compare([1, 3, 7, 6, 5, 10, 9], Result).
Result = [1,3,5,9] ?
yes
However, this predicate only works if the first list is variable free. You can't use it the other way round:
?- compare([A,B,C], [1,2]).
ERROR at clause 2 of user:compare/2 !!
INSTANTIATION ERROR- X is A+B: expected bound value
If you use library(clpfd) on the other hand ...
:- use_module(library(clpfd)).
compare([X],[X]).
compare([A,B|T],X):-
A #= B+1,
compare([B|T],X).
compare([A,B|T],[A|X]):-
A #\= B+1,
compare([B|T],X).
... the above query works too:
?- compare([A,B,C], [1,2]).
A = C = 2,
B = 1 ? ;
A = 1,
B = 3,
C = 2 ? ;
no

Mathematica select elements from list constrained by an analytic function

For some list of 2-d points,
e.g. data = {{1, 2}, {3,4}, {3, 6}},
and some analytic function, e.g. f[x] = x^2,
I want to select out only those points that lie beneath the curve, i.e., test for each point whether f[x] > y, and eliminate those points for which this is false.
I've tried to do this using Select. Something like: Select[data, #list1 > # [[2]] &][[All, 1]]
where list1 is a list of f[x] values generated by a list of random x values over some domain,
e.g. list1 = {3.285, 2.245, 7.413}
but to no avail. I suppose I am essentially trying to compare two lists (the second elements of data and list1), test which is bigger, and eliminate those points that fail the test. Any tips?
data = RandomReal[{0, 1}, {100, 2}];
f[x_] := x^2
data1 = Select[data, #[[2]] < f[#[[1]]] &];
Show[Plot[f[x], {x, 0, 1}], ListPlot#data1]

pair lists to create tuples in order

I'd like to combine two lists. If I have the following two lists: {a,b,c,d} and {1,2,3,4} what do I need to do so that I get {{a,1}, {b,2}, {c,3}, {d,4}}?
Here is one way:
Transpose[{{a, b, c, d}, {1, 2, 3, 4}}]
An esoteric method is Flatten, which (from the Help Section on Flatten) also allows Transpose of a 'ragged' array.
Flatten[ {{a, b, c, d}, {1, 2, 3, 4, 5}}, {{2}, {1}}]
Out[6]= {{a, 1}, {b, 2}, {c, 3}, {d, 4}, {5}}
One possible solution is
MapThread[List,{{a,b,c,d},{1,2,3,4}}]
If you have lists with the columns of a matrix:
l = Table[Subscript[g, Sequence[j, i]], {i, 5}, {j, 5}]
Transpose will give you the rows:
Transpose#l // MatrixForm
listA={a,b,c,d};
listB=[1,2,3,4};
table=Transpose#{# & ### listA, # & ### listB}
This is a great question. I had become stuck thinking there was a default way to do this with Table, but not so. The answers below are fairly intuitive, and can be easily generalized to other similar situations.
l1 = {a,b,c,d};
l2 = {1,2,3,4};
pairs = Table[{l1[[i]], l2[[i]]}, {i, 1, Length[l1]}]
MapThread does this sort of thing also. This is less elegant than Howard's MapThread solution, but also more readable in some sense. Look at MapThread docs. The function is defined inline (pure function):
pairs = MapThread[{#1, #2} &, {l1, l2}]
In case a, b, c, d themselves are also list, use the following:
MapThread[Flatten[{#1[[All]],#2}]&,{l1,l2}]//TableForm

What's the reason of using ; in F# lists instead of ,?

This might be a strange question but if I want to define a list of integers from:
1, 2, 3, 4, 5, 6, 7, 8, 9
Do I need to do it using the ; character?
[ 1; 2; 3; 4; 5; 6; 7; 8; 9 ]
instead of?:
[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
It just seems to me , is more natural and easy on the eyes. Just wondering the idea behind using ;? (Not criticizing)
Yes you must. The reason why is that in F# the comma operator is used for tuple expressions. So the expression 1,2,...9 is interpreted as a single tuple with 9 values.
[1,2] // List with 1 element that is a tuple value - (int*int) list
[1;2] // List with 2 elements that are integer values - int list
Other answers have pointed out the main reason.
As an aside it is worth noting that, like most other places that semicolon is used in the language, an alternative is a newline. For example
[ "foo"; "bar"; "baz" ]
can also be written as
[ "foo"
"bar"
"baz" ]
or a variety of other layouts where semicolons are replaced by newlines.
[1,2,3,4,5] is a list of 1 element of type int * int * int * int * int
[1;2;3;4;5] is a list of 5 elements of type int
also, list comprehensions and ranges are your friends
let bar = [1..9], 1..9 is a range so it get's unfolded into 1;2;3;...9;
let blort = [for i in 1..9 -> i] is a comprehension that does the same thing -- a little more power for some performance issues.
Edit: for completeness sake, you can also do
let foo = [1
2
3]
and get a list of [1;2;3]
Just wondering the idea behind using ;?
Tuples are more common in ML and using ; lets you write lists of tuples as:
[1, 2; 3, 4]
Historically, F# inherited this syntax from OCaml which created its syntax by trying to remove more superfluous parentheses from Standard ML syntax.