Our World Statistics Day conversations have been a great reminder of how much statistics can inform our lives. Do you have an example of how statistics has made a difference in your life? Share your story with the Community!
Highlighted
Level V

## How to Separate Matching Values in a List

Hi,

I have a list which could contain the following, for example: {22, 22, 22, 33, 33}. I want to be able to get the number of each unique value in the list, e.g. the number of 22's and the number of 33's. The problem is, I don't know how long my list will be and how many unique numbers there will be in the list. Is there any way in JSL to generalise a solution for this?

Thanks

1 ACCEPTED SOLUTION

Accepted Solutions
Highlighted
Super User

## Re: How to Separate Matching Values in a List

Table operations are probably the fastest way to do this.

``````my_list = {22, 22, 22, 33, 33};
dt = New Table( "Untitled", invisible, Add Rows( nitems(my_list) ),
New Column( "Column 1", Numeric, "Continuous", Format( "Best", 12 ),
Set Values( my_list )
)
);
dtab = dt << Tabulate(Show Control Panel( 0 ),
Add Table( Row Table( Grouping Columns( :Column 1 ) ) ));
dt2 = dtab << Make Into Data Table(invisible);
unique_value_list = dt2:column 1 << get values;
unique_count      = dt2:n << get values;
close(dt, nosave);
close(dt2, nosave);
show(unique_value_list, unique_count);``````
16 REPLIES 16
Highlighted
Level V

## Re: How to Separate Matching Values in a List

I've managed to get a list of the unique values like so {22, 33} using associative arrays and the << get key functionality but I still don't know how to get the number of each of those unique values in the original list.

Highlighted
Super User

## Re: How to Separate Matching Values in a List

Table operations are probably the fastest way to do this.

``````my_list = {22, 22, 22, 33, 33};
dt = New Table( "Untitled", invisible, Add Rows( nitems(my_list) ),
New Column( "Column 1", Numeric, "Continuous", Format( "Best", 12 ),
Set Values( my_list )
)
);
dtab = dt << Tabulate(Show Control Panel( 0 ),
Add Table( Row Table( Grouping Columns( :Column 1 ) ) ));
dt2 = dtab << Make Into Data Table(invisible);
unique_value_list = dt2:column 1 << get values;
unique_count      = dt2:n << get values;
close(dt, nosave);
close(dt2, nosave);
show(unique_value_list, unique_count);``````
Highlighted
Super User

## Re: How to Separate Matching Values in a List

Here is my variation on @pmroz solution.  It is more of an old school solution

``````my_list = {22, 22, 22, 33, 33};
dt = New Table( "Untitled",
private,
Add Rows( N Items( my_list ) ),
New Column( "Column 1",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Values( my_list )
)
);
// Use the Summary Platform to create the aggragate values
dtSum = dt << Summary(
private,
Group( :Column 1 ),
Freq( "None" ),
Weight( "None" )
);
// Create the new lists
unique_value_list = As List( dtSum:column 1 << get values );
unique_count = As List( dtSum:n rows << get values );
Close( dt, nosave );
Close( dtSum, nosave );
Show( unique_value_list, unique_count );``````
Jim
Highlighted
Super User

## Re: How to Separate Matching Values in a List

Don't forget summarize.  Even shorter.

``````my_list = {22, 22, 22, 33, 33};
dt = New Table( "Untitled", invisible, Add Rows( nitems(my_list) ),
New Column( "Column 1", Numeric, "Continuous", Format( "Best", 12 ),
Set Values( my_list )
)
);

summarize(dt, unique_value_list = by(:column1), unique_count = count(:column 1) );
show(unique_value_list, unique_count);
``````
Highlighted
Super User

## Re: How to Separate Matching Values in a List

@pmroz's response got me interested.  Because I usually try to avoid data tables if I can just because of the overhead.  I played with timings

``````names default to here(1);
my_list = {44, 33, 22, 33, 44};

repeat_list = [1, 5, 10, 50, 100, 1000,  2500, 5000, 7500, 10000];
dt_timing = new table("Timings",
new column("List Size"),
new column("Design"),
new column("Loop"),
new column("Summarize"),
);
for(ii=1, ii<=20, ii++,
for(ir = 1, ir <= nitems(repeat_list), ir++,
my_bigger_list = repeat(my_list, repeat_list[ir]);

// using design
st = HPTime();
aa = associative array(my_bigger_list);
keys = aa << Get Keys;
d = design(my_bigger_list, keys);
aa_design = associative array(keys, VSum(d));
time_design = HPTime() - st;

//using a loop
st = HPTime();
aa_loop = associative array(my_bigger_list, repeat(0, nitems(my_bigger_list)));
for(i=1, i<=nitems(my_bigger_list), i++,
aa_loop[my_bigger_list[i]]++;
);
time_loop = HPTime() - st;

//using a data table
st = HPTime();
dt = New Table( "Untitled", invisible, Add Rows( nitems(my_bigger_list) ),
New Column( "Column 1", Numeric, "Continuous", Format( "Best", 12 ),
Set Values( my_bigger_list )
)
);

summarize(dt, unique_value_list = by(:column1), unique_count = count(:column 1) );
close(dt, nosave);

aa_peter = associative array(unique_value_list, unique_count);
time_peter = HPTime()-st;
Eval(EvalExpr(
dt_timing << Add Rows({List Size = Expr(Nitems(my_bigger_list)), Design = Expr(time_design), Loop = Expr(time_loop), Summarize = Expr(time_peter)});
));

);
);

dt_stack = dt_timing << Stack(
columns( :Design, :Loop, :Summarize ),
Source Label Column( "Method" ),
Stacked Data Column( "Timing" )
);

close(dt_timing, no save);

biv = dt_stack << Bivariate(
Y( :Timing ),
X( :List Size ),
group by(:Method),
fit line(),
SendToReport(
Dispatch(
{},
"Bivar Plot",
FrameBox,
{Row Legend(
Method,
)}
),
)
);
``````

and obviously it depends on the list size.  But I ran it 20 times each on various list sizes and got this

Design was the fastest way I could find to do it.  And I definitely agree with @txnelson that I don't like Summarize because of it returning character always.

Vince Faller - Predictum
Highlighted
Community Manager

## Re: How to Separate Matching Values in a List

I agree with @pmroz and @txnelson, data tables make this easy.

I prefer the Summarize() function over Tabulate and Summary for this though.

``````my_list = {22, 22, 22, 33, 33};
dt = New Table( "Untitled",
private,
Add Rows( N Items( my_list ) ),
New Column( "Column 1",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Values( my_list )
)
);

summarize(dt, group=by(:column 1), n=count(:column 1));

show(group, n);``````

-Jeff
Highlighted
Super User

## Re: How to Separate Matching Values in a List

My support for the Summary Platform, is that the grouping variable is maintained as the same Data Type in the summary data table as it was in the originating data table.  In the Summarize() function, it is always returned as character values, even if the By column specified was numeric.

Jim
Highlighted
Level V

## Re: How to Separate Matching Values in a List

Thanks,

Would be useful if JMP included a find matching items / return matching items function for lists / associative arrays as they do for columns & rows.

Highlighted
Staff

## Re: How to Separate Matching Values in a List

Please post this suggestion in the Wish List area of the Community.

Learn it once, use it forever!
Article Labels

There are no labels assigned to this post.