Clear Filters
Clear Filters

Classifying things into kinds

2 views (last 30 days)
John Pryce
John Pryce on 5 Dec 2020
Commented: John Pryce on 5 Dec 2020
Increasingly often I want to do the following, so I want a simple vectorised way to do it - no "for" loops.
I have n things. Each thing is of one of m types. Coding the things as 1:n and the types as 1:m I can describe this data by an n-vector x where each x(j) is an integer in 1:m saying what type thing j has.
E.g. let n=7, m=5, then x = [2 3 1 3 5 1 2] says thing 1 has type 2, thing 2 has type 3 etc.
I want to convert between this form and the (obviously equivalent) form of a *partition* of 1:n into m subsets where the i'th subset lists all the things that have type i. This shall be a cell vector c of length m where c{i} is the set {j such that x(j)=i}, written as an ordinary vector in ascending order.
For the example, c is {[3], [1 7], [2 4], [] ,[5]}. Note c{4} is the empty vector because type 4 wasn't used.
Obviously, one can convert x to c and c to x by simple "for" loops but I want to avoid it.
I can do "x to c" by
c = arrayfun(@(i)find(x==i),1:m,'UniformOutput',false);
but (1) it looks clumsy, (2) implicitly it applies "find" to x a total of m times whereas a single pass through x should do.
Imagine n=10,000 and m=10, say. I welcome a better solution.
  2 Comments
John Pryce
John Pryce on 5 Dec 2020
Sorry I should have written c is {[3 6], [1 7], [2 4], [] ,[5]}.
John Pryce
John Pryce on 5 Dec 2020
Thanks! This is just what I was looking for.

Sign in to comment.

Accepted Answer

Ameer Hamza
Ameer Hamza on 5 Dec 2020
Edited: Ameer Hamza on 5 Dec 2020
You can use accumarray()
x = [2 3 1 3 5 1 2];
c = accumarray(x(:), (1:numel(x)), [], @(x) {x})
Result
>> c{:}
ans =
3
6
ans =
1
7
ans =
2
4
ans =
[]
ans =
5

More Answers (0)

Categories

Find more on Entering Commands in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!