Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Associative arrays?

0 views
Skip to first unread message

bill

unread,
Jun 12, 2003, 9:23:41 AM6/12/03
to


I'm a Perl programmer trying to teach myself Matlab, and having a
hard time getting my brain off its Perl track. I'm facing this
problem: I have a cell array S containing a sequence of symbols
(one symbol per cell). I also have another cell array A containing
the alphabet of the symbols that appear in S. In other words, the
entries in A are unique, and to every symbol in S there corresponds
a unique symbol in A. For example:

S = 'a' 'b' 'r' 'a' 'c' 'a' 'd' 'a' 'b' 'r' 'a'
A = 'a' 'b' 'r' 'c' 'd'

I want to produce a numeric array T obtained by replacing every
entry in S by its position in A. Continuing the example above, T
would be

T = 1 2 3 1 4 1 5 1 2 3 1

In Perl, I would solve this as follows. First, let

@S = ('a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a');
@A = ('a', 'b', 'r', 'c', 'd');

Now, define $a as the length of @A; in Perl:

$a = @A;

Next, define the hash (aka associative array) %d by

@d{@A} = 1..$a;

Now I would get my desired Perl array @T by

for $i (0..$#S) { # $#S is Perl for "the largest index of @S"
$T = $d{$S[$i]};
}

or more slickly by

@T = @d{@S};

Note that this Perl solution is general; in particular the code
would not change if one redefined @A.

What's the "Matlab Way" to achieve the same result in an equally
general way? (I emphasize generality with respect to the definition
of A, because this requirement rules out a solution that relies on
a switch statement.)

Thanks!

b.

Richard Lang

unread,
Jun 12, 2003, 9:39:57 AM6/12/03
to
S = {'a' 'b' 'r' 'a' 'c' 'a' 'd' 'a' 'b' 'r' 'a'};
A = {'a' 'b' 'r' 'c' 'd'};

[ignore, T] = ismember(S,A)

ignore =

1 1 1 1 1 1 1 1 1 1 1

T =

1 2 3 1 4 1 5 1 2 3 1

Richard

"bill" <bill_k...@yahoo.com> wrote in message
news:bc9ust$sio$1...@reader1.panix.com...

bill

unread,
Jun 12, 2003, 10:08:48 AM6/12/03
to
In <bc9vr8$u6f$1...@sabina.mathworks.co.uk> "Richard Lang" <rl...@mathworks.com> writes:

>S = {'a' 'b' 'r' 'a' 'c' 'a' 'd' 'a' 'b' 'r' 'a'};
>A = {'a' 'b' 'r' 'c' 'd'};

>[ignore, T] = ismember(S,A)

> ignore =

> 1 1 1 1 1 1 1 1 1 1 1

>T =

> 1 2 3 1 4 1 5 1 2 3 1


]<ewl!

Thanks!!

b.

bill

unread,
Jun 12, 2003, 10:33:25 AM6/12/03
to
In <bca1hg$8c$1...@reader1.panix.com> bill <bill_k...@yahoo.com> writes:

>In <bc9vr8$u6f$1...@sabina.mathworks.co.uk> "Richard Lang" <rl...@mathworks.com> writes:

>>S = {'a' 'b' 'r' 'a' 'c' 'a' 'd' 'a' 'b' 'r' 'a'};
>>A = {'a' 'b' 'r' 'c' 'd'};

>>[ignore, T] = ismember(S,A)

>> ignore =

>> 1 1 1 1 1 1 1 1 1 1 1

>>T =

>> 1 2 3 1 4 1 5 1 2 3 1


>]<ewl!


I spoke too soon. When I try the above, I get the error:

>> [ignore, T] = ismember(S,A)
??? Error using ==> ismember
Too many output arguments.

What version of Matlab are you using? I'm using version 6.0.0.88
(R12).

Also, when I read the documentation for ISMEMBER I noticed that
the Matlab version above may be significantly less general than
the Perl version I posted. The Perl version doesn't care whether
@S and @A contain strings or integers or floats, or any mixture of
them; it works correctly in all cases:

@S = ('xyz', 1.23, 1.23, 4.56, 4.56, 4.56, 1.23);
@A = (1.23, 4.56, 'xyz');

@d{@A} = 1..@A;

@T = @d{@S};

@T: 3 1 1 2 2 2 1


Can the Matlab version above handle the case in which A and S are
cell arrays containing numbers and/or strings?

b.

Richard Lang

unread,
Jun 12, 2003, 12:55:31 PM6/12/03
to

"bill" <bill_k...@yahoo.com> wrote in message
news:bca2vl$qr$1...@reader1.panix.com...

> In <bca1hg$8c$1...@reader1.panix.com> bill <bill_k...@yahoo.com> writes:
>
> >In <bc9vr8$u6f$1...@sabina.mathworks.co.uk> "Richard Lang"
<rl...@mathworks.com> writes:
>
> >>S = {'a' 'b' 'r' 'a' 'c' 'a' 'd' 'a' 'b' 'r' 'a'};
> >>A = {'a' 'b' 'r' 'c' 'd'};
>
> >>[ignore, T] = ismember(S,A)
>
> >> ignore =
>
> >> 1 1 1 1 1 1 1 1 1 1 1
>
> >>T =
>
> >> 1 2 3 1 4 1 5 1 2 3 1
>
>
> >]<ewl!
>
>
> I spoke too soon. When I try the above, I get the error:
>
> >> [ignore, T] = ismember(S,A)
> ??? Error using ==> ismember
> Too many output arguments.
>
> What version of Matlab are you using? I'm using version 6.0.0.88
> (R12).

You're right, this capability only exists in R13, Matlab v6.5. Here's
another version that works in v6.1, but it is a bit more convoluted
unfortunately:

[ignore, ignore, idx] = unique([A, S]);
[ignore, idx2] = sort(idx(1:length(A)));
T = idx2(idx(length(A)+1:end))

I don't have an earlier installation to hand but I think I remember these
features being around for a while.


> Also, when I read the documentation for ISMEMBER I noticed that
> the Matlab version above may be significantly less general than
> the Perl version I posted. The Perl version doesn't care whether
> @S and @A contain strings or integers or floats, or any mixture of
> them; it works correctly in all cases:
>
> @S = ('xyz', 1.23, 1.23, 4.56, 4.56, 4.56, 1.23);
> @A = (1.23, 4.56, 'xyz');
>
> @d{@A} = 1..@A;
>
> @T = @d{@S};
>
> @T: 3 1 1 2 2 2 1
>
>
> Can the Matlab version above handle the case in which A and S are
> cell arrays containing numbers and/or strings?

Unfortunately it can't. I can't find anything better than a good old
double-loop:

T = zeros(size(S));
for n = 1:length(S)
for m = 1:length(A)
if isequal(S{n}, A{m})
T(n) = m;
break
end
end
end


Richard


0 new messages