Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
Do stuff without colons

Subject: Do stuff without colons

From: Pithawat

Date: 9 Dec, 2008 20:35:03

Message: 1 of 25

Hello, I'd like to know if anyone can help me with this seemingly simple problem...

I want to know if it's possible to swap colon notation with a built in function. Let me give an example:

a = randperm(100);
b = a(1:10); % Choose only first 10 random permutations

Is it possible to combine these two lines into one:

b = function(randperm(100), 1:10);

or something along the line

b = randperm(100)(1:10);

This would really make my life so much easier!

Am I missing something here?

Pithawat

Subject: Do stuff without colons

From: Matt

Date: 9 Dec, 2008 20:40:23

Message: 2 of 25

"Pithawat " <tanvach+matlab@gmail.com> wrote in message <ghmkpn$9ml$1@fred.mathworks.com>...
> Hello, I'd like to know if anyone can help me with this seemingly simple problem...
>
> I want to know if it's possible to swap colon notation with a built in function. Let me give an example:
>
> a = randperm(100);
> b = a(1:10); % Choose only first 10 random permutations
>
> Is it possible to combine these two lines into one:
>
> b = function(randperm(100), 1:10);
>
> or something along the line
>
> b = randperm(100)(1:10);
>
> This would really make my life so much easier!
>
> Am I missing something here?
>
> Pithawat


b=ceil(100*rand(1,10));

Subject: Do stuff without colons

From: someone

Date: 9 Dec, 2008 20:44:03

Message: 3 of 25

"Pithawat " <tanvach+matlab@gmail.com> wrote in message <ghmkpn$9ml$1@fred.mathworks.com>...
> Hello, I'd like to know if anyone can help me with this seemingly simple problem...
>
> I want to know if it's possible to swap colon notation with a built in function. Let me give an example:
>
> a = randperm(100);
> b = a(1:10); % Choose only first 10 random permutations
>
> Is it possible to combine these two lines into one:
>
> b = function(randperm(100), 1:10);
>
> or something along the line
>
> b = randperm(100)(1:10);
>
> This would really make my life so much easier!
>
> Am I missing something here?
>
> Pithawat

% Write your very own little function and make it a seperate m-file:

b = MyOwnFuntion(n,m)
a = randperm(n);
m = min(m,n) % some error checking
b = a(1:m); % Choose only first m random permutations (m<n)


% Now instead of:
%b = randperm(100)(1:10);
% use
b = MyOwnFuntion(100,10)

Subject: Do stuff without colons

From: Walter Roberson

Date: 9 Dec, 2008 20:46:42

Message: 4 of 25

Matt wrote:
> "Pithawat " <tanvach+matlab@gmail.com> wrote in message <ghmkpn$9ml$1@fred.mathworks.com>...

>> a = randperm(100);
>> b = a(1:10); % Choose only first 10 random permutations

>> Is it possible to combine these two lines into one:

> b=ceil(100*rand(1,10));

That's not equivalent!! randperm is selection without replacement; rand() is selection
-with- replacement.
 
firstN = @(v,n) v(1:N);
a = firstN(randperm(100),10);

OR, using only built-in functions,

subsref(randperm(100),struct('type','()','subs',{{1:10}}))

--
.signature note: I am now avoiding replying to unclear or ambiguous postings.
Please review questions before posting them. Be specific. Use examples of what you mean,
of what you don't mean. Specify boundary conditions, and data classes and value
relationships -- what if we scrambled your data or used -Inf, NaN, or complex(rand,rand)?

Subject: Do stuff without colons

From: Matt

Date: 9 Dec, 2008 20:49:02

Message: 5 of 25

"Matt" <mjacobson.removethis@xorantech.com> wrote in message <ghml3n$eoe$1@fred.mathworks.com>...
> "Pithawat " <tanvach+matlab@gmail.com> wrote in message <ghmkpn$9ml$1@fred.mathworks.com>...
> > Hello, I'd like to know if anyone can help me with this seemingly simple problem...
> >
> > I want to know if it's possible to swap colon notation with a built in function. Let me give an example:
> >
> > a = randperm(100);
> > b = a(1:10); % Choose only first 10 random permutations
> >
> > Is it possible to combine these two lines into one:
> >
> > b = function(randperm(100), 1:10);
> >
> > or something along the line
> >
> > b = randperm(100)(1:10);
> >
> > This would really make my life so much easier!
> >
> > Am I missing something here?
> >
> > Pithawat
>
>
> b=ceil(100*rand(1,10));


Sorry, I realize now that this won't work. It samples 1:100 with replacement.

Is the idea here simply to save typing? If so, "someone"'s solution is a reasonable one.

Or, is the idea to cut down on the number of randomization operations you have to do? If the latter, you must be doing randperm(N) for very large N to make this worthwhile.

Subject: Do stuff without colons

From: someone

Date: 9 Dec, 2008 20:49:02

Message: 6 of 25

"someone" <someone@somewhere.net> wrote in message <ghmlaj$inl$1@fred.mathworks.com>...
> "Pithawat " <tanvach+matlab@gmail.com> wrote in message <ghmkpn$9ml$1@fred.mathworks.com>...
> > Hello, I'd like to know if anyone can help me with this seemingly simple problem...
> >
> > I want to know if it's possible to swap colon notation with a built in function. Let me give an example:
> >
> > a = randperm(100);
> > b = a(1:10); % Choose only first 10 random permutations
> >
> > Is it possible to combine these two lines into one:
> >
> > b = function(randperm(100), 1:10);
> >
> > or something along the line
> >
> > b = randperm(100)(1:10);
> >
> > This would really make my life so much easier!
> >
> > Am I missing something here?
> >
> > Pithawat
>
> % Write your very own little function and make it a seperate m-file:
>
> b = MyOwnFuntion(n,m)
> a = randperm(n);
> m = min(m,n) % some error checking
> b = a(1:m); % Choose only first m random permutations (m<n)
>
>
> % Now instead of:
> %b = randperm(100)(1:10);
> % use
> b = MyOwnFuntion(100,10)
>
>
>
% Oops, first line shoud be:
function b = MyOwnFuntion(n,m)

Subject: Do stuff without colons

From: Pithawat

Date: 9 Dec, 2008 20:50:17

Message: 7 of 25

Sorry Matt, but that would give the same result.

In any case I am looking for a more general built in function.

Thanks any way though.


"Matt" <mjacobson.removethis@xorantech.com> wrote in message <ghml3n$eoe$1@fred.mathworks.com>...
> "Pithawat " <tanvach+matlab@gmail.com> wrote in message <ghmkpn$9ml$1@fred.mathworks.com>...
> > Hello, I'd like to know if anyone can help me with this seemingly simple problem...
> >
> > I want to know if it's possible to swap colon notation with a built in function. Let me give an example:
> >
> > a = randperm(100);
> > b = a(1:10); % Choose only first 10 random permutations
> >
> > Is it possible to combine these two lines into one:
> >
> > b = function(randperm(100), 1:10);
> >
> > or something along the line
> >
> > b = randperm(100)(1:10);
> >
> > This would really make my life so much easier!
> >
> > Am I missing something here?
> >
> > Pithawat
>
>
> b=ceil(100*rand(1,10));

Subject: Do stuff without colons

From: Matt Fig

Date: 9 Dec, 2008 20:54:02

Message: 8 of 25

I have wanted a built-in operator that does this kind of thing for a while. Something like ->

b = randperm(100) ->(1:10);

This comes up when creating a cell array for no purpose except to use {:} too. But we don't have one.

Subject: Do stuff without colons

From: Pithawat

Date: 9 Dec, 2008 20:59:02

Message: 9 of 25

"Matt" <mjacobson.removethis@xorantech.com> wrote in message <ghmlju$ndi$1@fred.mathworks.com>...
> "Matt" <mjacobson.removethis@xorantech.com> wrote in message <ghml3n$eoe$1@fred.mathworks.com>...
> > "Pithawat " <tanvach+matlab@gmail.com> wrote in message <ghmkpn$9ml$1@fred.mathworks.com>...
> > > Hello, I'd like to know if anyone can help me with this seemingly simple problem...
> > >
> > > I want to know if it's possible to swap colon notation with a built in function. Let me give an example:
> > >
> > > a = randperm(100);
> > > b = a(1:10); % Choose only first 10 random permutations
> > >
> > > Is it possible to combine these two lines into one:
> > >
> > > b = function(randperm(100), 1:10);
> > >
> > > or something along the line
> > >
> > > b = randperm(100)(1:10);
> > >
> > > This would really make my life so much easier!
> > >
> > > Am I missing something here?
> > >
> > > Pithawat
> >
> >
> > b=ceil(100*rand(1,10));
>
>
> Sorry, I realize now that this won't work. It samples 1:100 with replacement.
>
> Is the idea here simply to save typing? If so, "someone"'s solution is a reasonable one.
>
> Or, is the idea to cut down on the number of randomization operations you have to do? If the latter, you must be doing randperm(N) for very large N to make this worthwhile.

I'm looking for a way to keep my variables in m files to minimum, this helps to make it more readable.

It's also for typing inside input() function call so you can do some funky stuff when asked to enter something.

But really it's because I'm very surprised MATLAB doesn't have something so simple as treating array output from a function as array. Just doesn't make sense to me.

Subject: Do stuff without colons

From: John D'Errico

Date: 9 Dec, 2008 21:16:02

Message: 10 of 25

"Matt" <mjacobson.removethis@xorantech.com> wrote in message <ghml3n$eoe$1@fred.mathworks.com>...
> "Pithawat " <tanvach+matlab@gmail.com> wrote in message <ghmkpn$9ml$1@fred.mathworks.com>...

> > b = randperm(100)(1:10);
> >
> > This would really make my life so much easier!
> >
> > Am I missing something here?
> >
> > Pithawat
>
>
> b=ceil(100*rand(1,10));

You don't realize that this is NOT a valid
substitute for randperm? Worse, it does not
even address the question posed by the OP?

John

Subject: Do stuff without colons

From: Pithawat

Date: 9 Dec, 2008 21:47:01

Message: 11 of 25

The closest thing I've come across is colon() function. However, this can only substitute n:m type syntax but not a(n:m).

A subset of this function is really easy to implement:

function out = manipulate(A,B)
out = A(B);

So to solve my original question: manipulate(randperm(100),1:10)

But it doesn't work for things like :

a = randperm(100);
b = a(end/2:end)

I'm sure there must be a function hidden somewhere!

Subject: Do stuff without colons

From: Doug Schwarz

Date: 9 Dec, 2008 21:50:20

Message: 12 of 25

In article <ghmm6m$7r9$1@fred.mathworks.com>,
 "Pithawat " <tanvach+matlab@gmail.com> wrote:


> But really it's because I'm very surprised MATLAB doesn't have something so
> simple as treating array output from a function as array. Just doesn't make
> sense to me.

Yes, it would be nice to be able to write

  randperm(100)(1:10)

but the problem is that sometimes the syntax will be ambiguous. Suppose
you have a function, f, that implements the randperm(100) operation, but
can operate with no input argument:

  function x = f(n)
  if nargin == 0
      n = 100;
  end
  x = randperm(n);

Now, what does the parser do with

  f(2) ?

Does it call f with no arguments and then return the second value or
does it call f with the argument = 2?

Okay, TMW could define what it does, but it seems to me that this would
be a source of confusion, especially for beginners.

I don't know if that's the reason that it has never been implemented.

I wouldn't mind if we were required to supply empty parentheses () if we
want to run f with no arguments and maybe that would resolve the
ambiguity, but it certainly would break old code. You'd also have to
write things like

  radians = degrees*pi()/180;

--
Doug Schwarz
dmschwarz&ieee,org
Make obvious changes to get real email address.

Subject: Do stuff without colons

From: Matt

Date: 9 Dec, 2008 21:50:24

Message: 13 of 25

"Matt Fig" <spamanon@yahoo.com> wrote in message <ghmlta$s44$1@fred.mathworks.com>...
> I have wanted a built-in operator that does this kind of thing for a while. Something like ->
>
> b = randperm(100) ->(1:10);
>
> This comes up when creating a cell array for no purpose except to use {:} too. But we don't have one.

You can pretty much get this effect by wrapping any function handle in an object with an overloaded subsref method. Something like below (note: I'm still using old-style class definitions...)

%%%The functions below would go in an a class directory called @IndexableFunction

function f=IndexableFunction(h)
%Class constructor
%
%h is a handle to a function which object f will represent

...
f.h=h;
f=class(f,'IndexableFunction');
...

%%%%
function out=subref(f,S)
%SUBSREF method for @IndexableFunction class
%
%The function is called by passing arguments in braces
%
% A=f{arg1,arg2,arg3,...}
%
% is equivalent to f.h(arg1,arg2,arg3,...)
%
%Subsequent indexing of the output will also be be possible, e.g.
%
% f{arg1,arg2,...}(1:10)
%
%will be equivalent to A(1:10)

switch S(1).type

  case '{}'
    out=f.h(S(1).subs{:});

  otherwise
   error 'Bad syntax'

end

 out=subsref(out,S(2:end));



 

Subject: Do stuff without colons

From: Matt

Date: 9 Dec, 2008 22:28:02

Message: 14 of 25

"John D'Errico" <woodchips@rochester.rr.com> wrote in message <ghmn6i$5s0$1@fred.mathworks.com>...
> You don't realize that this is NOT a valid
> substitute for randperm? Worse, it does not
> even address the question posed by the OP?
>
> John

Yes.

But I think Pithawat will get over it.

Subject: Do stuff without colons

From: Steve Eddins

Date: 9 Dec, 2008 22:34:56

Message: 15 of 25

Doug Schwarz wrote:
> In article <ghmm6m$7r9$1@fred.mathworks.com>,
> "Pithawat " <tanvach+matlab@gmail.com> wrote:
>
>
>> But really it's because I'm very surprised MATLAB doesn't have something so
>> simple as treating array output from a function as array. Just doesn't make
>> sense to me.
>
> Yes, it would be nice to be able to write
>
> randperm(100)(1:10)
>
> but the problem is that sometimes the syntax will be ambiguous. Suppose
> you have a function, f, that implements the randperm(100) operation, but
> can operate with no input argument:
>
> function x = f(n)
> if nargin == 0
> n = 100;
> end
> x = randperm(n);
>
> Now, what does the parser do with
>
> f(2) ?
>
> Does it call f with no arguments and then return the second value or
> does it call f with the argument = 2?
>
> Okay, TMW could define what it does, but it seems to me that this would
> be a source of confusion, especially for beginners.
>
> I don't know if that's the reason that it has never been implemented.

That's one of the most important reasons. Overloading of () to mean
represent both indexing expressions and function argument lists already
causes some confusion.

>
> I wouldn't mind if we were required to supply empty parentheses () if we
> want to run f with no arguments and maybe that would resolve the
> ambiguity, but it certainly would break old code. You'd also have to
> write things like
>
> radians = degrees*pi()/180;
>

Many of us would like to see this kind of chained indexing supported by
the language, but the issues mentioned by Doug are hard to address.

It might happen someday. Or it might not.

I've been at MathWorks for 15 years (as of yesterday!), and this
discussion has been going on in one form or another for just about the
whole time. :-)

---
Steve Eddins
http://blogs.mathworks.com/steve/

Subject: Do stuff without colons

From: Pithawat

Date: 9 Dec, 2008 23:06:01

Message: 16 of 25

Thank you everyone for your replies.

Doug:
That's a valid point, I guess there are certain cases that a confusion might occur, especially since MATLAB is design to be backwards compatible. Maybe something like this is better:

[A B](end/2:end)
or
[randperm(100)](end/2:end)

Matt:
Thanks, you have an interesting heavy weight solution. Would the braces be able to stack together?

Steve:
Judging from the simplicity of needing something like this, I can see why it's been discussed many times... Do you remember some elegant solution you might care to share?

Subject: Do stuff without colons

From: Pithawat

Date: 9 Dec, 2008 23:08:02

Message: 17 of 25

Thank you everyone for your replies.

Doug:
That's a valid point, I guess there are certain cases that a confusion might occur, especially since MATLAB is design to be backwards compatible. Maybe something like this is better:

[A B](end/2:end)
or
[randperm(100)](end/2:end)

Matt:
Thanks, you have an interesting heavy weight solution. Would the braces be able to stack together?

Steve:
Judging from the simplicity of needing something like this, I can see why it's been discussed many times... Do you remember some elegant solution you might care to share?

Subject: Do stuff without colons

From: Matt Fig

Date: 10 Dec, 2008 00:28:02

Message: 18 of 25

Doug Schwarz <see@sig.for.address.edu> wrote in message
> function x = f(n)
> if nargin == 0
> n = 100;
> end
> x = randperm(n);
>
> Now, what does the parser do with
>
> f(2) ?
>
> Does it call f with no arguments and then return the second value or
> does it call f with the argument = 2?


I think the operator approach I suggested above could avoid this, or am I missing other problems?

f -> (2) % Call with no args, call second value
f(2) % Call f with arg 2.


> Doug Schwarz
> dmschwarz&ieee,org
> Make obvious changes to get real email address.

Subject: Do stuff without colons

From: Steve Eddins

Date: 10 Dec, 2008 14:49:40

Message: 19 of 25

Pithawat wrote:
> Steve: Judging from the simplicity of needing something like this, I
> can see why it's been discussed many times... Do you remember some
> elegant solution you might care to share?

<tongue-partially-in-cheek>

Nothing simpler than this:

temp = foo();
out = temp(1:5);

</tongue-partially-in-cheek>

Subject: Do stuff without colons

From: Jos

Date: 10 Dec, 2008 15:39:02

Message: 20 of 25

Steve Eddins <Steve.Eddins@mathworks.com> wrote in message <ghoku4$esh$1@fred.mathworks.com>...
> Pithawat wrote:
> > Steve: Judging from the simplicity of needing something like this, I
> > can see why it's been discussed many times... Do you remember some
> > elegant solution you might care to share?
>
> <tongue-partially-in-cheek>
>
> Nothing simpler than this:
>
> temp = foo();
> out = temp(1:5);
>
 
or use the one-liner:
temp = foo(); temp = temp(1:5);
 
> </tongue-partially-in-cheek>
 
;-)
Jos

Subject: Do stuff without colons

From: Pithawat

Date: 10 Dec, 2008 15:48:02

Message: 21 of 25

Walter Roberson <roberson@hushmail.com> wrote in message
> firstN = @(v,n) v(1:N);
> a = firstN(randperm(100),10);
>
> OR, using only built-in functions,
>
> subsref(randperm(100),struct('type','()','subs',{{1:10}}))

Thanks Walter, I've completely missed your solution. Subsref looks like the only one line solution I can find, so yes you have answered my question. Although I'm now using the anonymous function handle route by predeclaring:

foo = @(a,b) a(b);

so I can now use foo(randperm(100),1:10) with ease.

Hopefully Mathworks will restore sanity sometime in the near future.

Subject: Do stuff without colons

From: Oliver Woodford

Date: 16 Dec, 2008 14:07:02

Message: 22 of 25

"Pithawat " wrote:
> I want to know if it's possible to swap colon notation with a built in function. Let me give an example:
>
> a = randperm(100);
> b = a(1:10); % Choose only first 10 random permutations

This is slightly off topic, but I think it would be well worth randperm having an optional second parameter indicating how many numbers you want back. i.e.
a = randperm(1e6, 5);
be equivalent to
a = randperm(1e6);
a = a(1:5);
This would save time, and possibly (depending on the internal method) unnecessary allocation of memory, when you want to extract a small number variables from unique random locations in a large array. Certainly I'd use this functionality a lot in my work.

Subject: Do stuff without colons

From: Jos

Date: 16 Dec, 2008 14:20:17

Message: 23 of 25

"Oliver Woodford" <o.j.woodford.98@cantab.net> wrote in message <gi8cm6$ktp$1@fred.mathworks.com>...
> "Pithawat " wrote:
> > I want to know if it's possible to swap colon notation with a built in function. Let me give an example:
> >
> > a = randperm(100);
> > b = a(1:10); % Choose only first 10 random permutations
>
> This is slightly off topic, but I think it would be well worth randperm having an optional second parameter indicating how many numbers you want back. i.e.
> a = randperm(1e6, 5);
> be equivalent to
> a = randperm(1e6);
> a = a(1:5);
> This would save time, and possibly (depending on the internal method) unnecessary allocation of memory, when you want to extract a small number variables from unique random locations in a large array. Certainly I'd use this functionality a lot in my work.

If you use this functionality a lot, I suggest you modify randperm slightly, and save it in a higher directory on your path, as I have done as well.

Jos

Subject: Do stuff without colons

From: Walter Roberson

Date: 16 Dec, 2008 18:10:26

Message: 24 of 25

Oliver Woodford wrote:
> This is slightly off topic, but I think it would be well worth randperm having an optional
> second parameter indicating how many numbers you want back. i.e.
> a = randperm(1e6, 5);
> be equivalent to
> a = randperm(1e6);
> a = a(1:5);
> This would save time, and possibly (depending on the internal method) unnecessary
> allocation of memory, when you want to extract a small number variables from unique
> random locations in a large array.

I haven't specifically studied the mathematics of this, but as far as I am -aware-, to
randomly select without replacement (as randperm requires) with less memory than
the number of numbers involved, requires methods that generate individual new numbers
and reject them if they have already been selected, or methods that generate sets of numbers
and reject the entire set if any duplicates are found. The problem with both of those
approaches is that they have exponential waiting times, particularly as the number of
numbers to be generated approaches the size of the selection set.

It could be that there is another approach currently unknown to me. I seem to recall
that I have read of at least one scheme that -reduces- the rejection rate by working
with generated triples of numbers, but my understanding is that that scheme still has
an exponential waiting time.

--
.signature note: I am now avoiding replying to unclear or ambiguous postings.
Please review questions before posting them. Be specific. Use examples of what you mean,
of what you don't mean. Specify boundary conditions, and data classes and value
relationships -- what if we scrambled your data or used -Inf, NaN, or complex(rand,rand)?

Subject: Do stuff without colons

From: Oliver Woodford

Date: 16 Dec, 2008 21:24:02

Message: 25 of 25

Walter Roberson <roberson@hushmail.com> wrote:
> Oliver Woodford wrote:
> > This is slightly off topic, but I think it would be well worth randperm having an optional
> > second parameter indicating how many numbers you want back. i.e.
> > a = randperm(1e6, 5);
> > be equivalent to
> > a = randperm(1e6);
> > a = a(1:5);
> > This would save time, and possibly (depending on the internal method) unnecessary
> > allocation of memory, when you want to extract a small number variables from unique
> > random locations in a large array.
>
> I haven't specifically studied the mathematics of this, but as far as I am -aware-, to
> randomly select without replacement (as randperm requires) with less memory than
> the number of numbers involved, requires methods that generate individual new numbers
> and reject them if they have already been selected, or methods that generate sets of numbers
> and reject the entire set if any duplicates are found.

That was my feeling too, (the 'possibly' was with regard to whether it was possible at all).

I've just noticed that randperm uses sort, which is slower than linear in the number of variables (n log n?), and I don't know of a MATLAB function which sorts to find only the first m numbers, so it's not possible to save time on it either if you only want m numbers. There is an approach with linear complexity which you could stop after the first m iterations, so could doubly speed things up (but not save memory, as you point out).

I've just done a quick check, and it does speed things up for larger n, but is generally slower for n < 1e4 (on my system), unless m << n:

function p = randperm2(n, m)
if nargin < 2
    m = n;
elseif m > n
    error('m > n')
end
p = 1:n;
I = ceil(rand(1, m) .* (n-1:-1:n-m)) + (1:m);
for a = 1:min(m,n-1)
   b = I(a);
   c = p(a);
   p(a) = p(b);
   p(b) = c;
end
p = p(1:m);

Typical times (after running each example a few times first):
>> tic; a = randperm(1e6); a = a(1:5); toc
Elapsed time is 0.275742 seconds.
>> tic; a = randperm2(1e6); a = a(1:5); toc
Elapsed time is 0.241612 seconds.
>> tic; a = randperm2(1e6, 5); toc
Elapsed time is 0.010763 seconds.

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us