build and use hash table using containers.Map - matlab

I'm trying to create an expanding lookup table. I think the cell array is what I want but I'm not sure. The structure would be initialized with rows, and an unknown amount of columns. I want to be able to append to the end of each row, and access all values from a specific row.
desired structure:
[1] [4,5] [6,7]
[2] [4,5] [6,7] [3,6]
...
[n] [R1,B2] [R2,B2] ... [Rm, Bm]
this is what I have so far
%%% Build the R-table
n = 360;
k = {};
v = {};
for i = 1:n
k{end+1} = i; % how would I get n keys without this loop?
v{end+1} = {}; % how would I get n values without this loop?
end
rTable = containers.Map(k, v);
%%% add R,B pair to key I
I = 1;
R_add = 4;
B_add = 5;
current_list_temp = rTable(I); % can I add without using a temp variable?
current_list_temp{end+1} = {[R_add, B_add]};
rTable(I) = current_list_temp;
%%% read values for Nth pair in the Ith key
I = 1;
N = 1;
temp = rTable(I); % can I read the values without using a temp variable?
R_read = temp{N}{1}(1);
B_read = temp{N}{1}(2);
Is there a better way of doing this?

When used for indexing end translates to the largest allowed index and you can manipulate it by adding or multiplying it, so instead of
first_empty_cell = ?
cell{index, first_free_cell} = [4,5]
try
cell{index, end+1} = [4,5]

Related

All possible combinations of many parameters MATLAB

I have a list of parameters and I need to evaluate my method over this list. Right now, I am doing it this way
% Parameters
params.corrAs = {'objective', 'constraint'};
params.size = {'small', 'medium', 'large'};
params.density = {'uniform', 'non-uniform'};
params.k = {3,4,5,6};
params.constraintP = {'identity', 'none'};
params.Npoints_perJ = {2, 3};
params.sampling = {'hks', 'fps'};
% Select the current parameter
for corrAs_iter = params.corrAs
for size_iter = params.size
for density_iter = params.density
for k_iter = params.k
for constraintP_iter = params.constraintP
for Npoints_perJ_iter = params.Npoints_perJ
for sampling_iter = params.sampling
currentParam.corrAs = corrAs_iter;
currentParam.size = size_iter;
currentParam.density = density_iter;
currentParam.k = k_iter;
currentParam.constraintP = constraintP_iter;
currentParam.Npoints_perJ = Npoints_perJ_iter;
currentParam.sampling = sampling_iter;
evaluateMethod(currentParam);
end
end
end
end
end
end
end
I know it looks ugly and if I want to add a new type of parameter, I have to write another for loop. Is there any way, I can vectorize this? Or maybe use 2 for loops instead of so many.
I tried the following but, it doesn't result in what I need.
for i = 1:numel(fields)
% if isempty(params.(fields{i}))
param.(fields{i}) = params.(fields{i})(1);
params.(fields{i})(1) = [];
end
What you need is all combinations of your input parameters. Unfortunately, as you add more parameters the storage requirements will grow quickly (and you'll have to use a large indexing matrix).
Instead, here is an idea which uses linear indicies of a (never created) n1*n2*...*nm matrix, where ni is the number of elements in each field, for m fields.
It is flexible enough to cope with any amount of fields being added to params. Not performance tested, although as with any "all combinations" operation you should be wary of the non-linear increase in computation time as you add more fields to params, note prod(sz)!
The code I've shown is fast, but the performance will depend entirely on which operations you do in the loop.
% Add parameters here
params.corrAs = {'objective', 'constraint'};
params.size = {'small', 'medium', 'large'};
params.density = {'uniform', 'non-uniform'};
% Setup
f = fieldnames( params );
nf = numel(f);
sz = NaN( nf, 1 );
% Loop over all parameters to get sizes
for jj = 1:nf
sz(jj) = numel( params.(f{jj}) );
end
% Loop for every combination of parameters
idx = cell(1,nf);
for ii = 1:prod(sz)
% Use ind2sub to switch from a linear index to the combination set
[idx{:}] = ind2sub( sz, ii );
% Create currentParam from the combination indices
currentParam = struct();
for jj = 1:nf
currentParam.(f{jj}) = params.(f{jj}){idx{jj}};
end
% Do something with currentParam here
% ...
end
Asides:
I'm using dynamic field name references for indexing the fields
I'm passing multiple outputs into a cell array from ind2sub, so you can handle a variable number of field names when ind2sub has one output for each dimension (or field in this use-case).
Here is a vectorized solution :
names = fieldnames(params).';
paramGrid = cell(1,numel(names));
cp = struct2cell(params);
[paramGrid{:}] = ndgrid(cp{:});
ng = [names;paramGrid];
st = struct(ng{:});
for param = st(:).'
currentParam = param;
end
Instead of nested loops we can use ndgrid to create the cartesian product of the cell entries so we can find all combinations of cell entries without loop.

Matlab Data Import from a text file

How do i import data of the following format.
1.0,X
.,-1.0
The size of the table may differ. As in the next file can also be a valid input file
.,.,.,1.0
.,X,.,-1.0
.,.,.,.
I have tried doing this using readtable to read the data and then use strcmp to assign the values to a different matrix but it doesnt work. What am i doing wrong.
Code:
foo = readtable(environment_file)
bar = zeros(size(foo,1),size(foo,2));
for i = 1:size(foo,1)
for j = 1:size(foo,2)
if strcmp(foo(i,j),'.')
bar(i,j) = 3;
elseif strcmp(foo(i,j),'X')
bar(i,j) = -10;
elseif strcmp(foo(i,j),'1.0')
bar(i,j) = 1;
elseif strcmp(foo(i,j),'-1.0')
bar(i,j) = -1;
end
end
end
bar
There are two problems in your code. One is that readtable reads the file as a table and takes the first row in the file as the names of the columns. So therefore, you should have the names at the top of the file.
Secondly, to access the contents of the table you need to use {} and not (). Also, there is no need to use for loops as you can use logical indexing to assign values to your matrix bar_b. Therefore, the changed code is as follows:
dataArray = readtable('environment_file.txt');
[n, m] = size(dataArray);
bar_b = zeros(n, m);
bar_b(strcmp(dataArray{:, :}, '.')) = 3;
bar_b(strcmp(dataArray{:, :}, 'X')) = -10;
bar_b(strcmp(dataArray{:, :}, '1.0')) = 1;
bar_b(strcmp(dataArray{:, :}, '-1.0')) = -1;

MATLAB: Find function within range

How can I use the find function within specific ranges.
Say, I have an array arr1 with random values. I have the start & end indices of the portions I'd like to analyze (in this example, I want to find the first occurrence for when the value is larger than 0.8)
How could the find function be used here with start and end indices and the condition as well?
For example:
arr1 = rand(1000,1);
start_ind = [100;500;850];
end_ind = [160;620;925];
for i = 1:length(start_ind)
output = find(arr1(start_ind(i):end_ind(i)) >=0.8); % ????
end
Much appreciated,
Use the second argument of find to only get the first match. You can then shift indices by adding start_ind - 1:
arr1 = rand(1000,1);
start_ind = [100; 500; 850];
end_ind = [160; 620; 925];
output = zeros(length(start_ind), 1);
for i = 1:length(start_ind)
output(i) = find(arr1(start_ind(i):end_ind(i)) >=0.8, 1) + start_ind(i) - 1;
end

Fill matrix with function values in Matlab

I've got 3 functions, oe1(n), oe2(n) and oe3(n).
I want to create a matrix representing the function values.
The structure of the matrix should be like this:
A = [oe1(0) oe2(0) oe3(0); oe1(1) oe2(1) od3(1); ...... ; oe1(N-1), oe2(N-1), oe3(N-1)];
I've tried filling it with a for loop, but it does not work.
Is there a standard Matlab operation for this? I really can't figure out how to do it.
Anders.
oe1(n1) = sin(2*pi*F*n1+phi)
oe2(n1) = ones(length(n1),1);
oe3(n1) = n1*Ts
pol = (oe2)'
vector_x = [a; b; c];
vector_veardier = [oe1(n1), 1, oe3(n1)]
xi = 1:N-1;
for i = 2:N-1;
for j = 1:3
vector_veardier(i, j) = oe1(j);
end
end
Do your functions accept vectors? If so you can use:
A = [oe1((1:N)'), oe2((1:N)'), oe3((1:N)')];
but otherwise you might have to use arrayfun:
A = [arrayfun(#oe1, (1:N)'), arrayfun(#oe2, (1:N)'), arrayfun(#oe3, (1:N)')];
Note that in your provided code you have not defined oeN as functions, but as some kind of array with a value inserted at position n1.
One way to do it with a for loop would however be:
A = zeros(N,3);
for i = 1:N,
A(i,:) = [oe1(i), oe2(i) oe3(i)];
end

Removing repeated elements in a list of words and counting the number of repetitions

This is my code, I am trying to sort an array of words, and calling the sorted array 'a'.
I am trying to use a while loop to compare adjacent elements of a, and as it is sorted any repetitions should already be next to each other. If there is a repetition I remove the word and and it to the count. I am unsure how to get my output to show each sorted word and its associated count together. Thank you for any help.
(myAsort is a function I have already made that puts words into alphabetical order)
For example if I input myACsort({'cat','dog','cat'), I want the output to be:
answer =
'cat' 'dog'
count:2 count:1
function [ answer ]= myACsort( input )
%UNTITLED2 Summary of this function goes here
% Detailed explanation goes here
a = myAsort(input);
n = length(a);
i = 1;
count = 1;
while (i<=n)
if isequal(a{i},a{i+1})
a(i+1) = [];
count = count+1;
else
count = 1;
i=i+1;
end
end
end
The usual combination of unique and accumarray would be my suggestion:
>> strs = {'cat','dog','cat'};
>> [uStr,ia,ic] = unique(strs);
>> countCell = [uStr(:).'; num2cell(accumarray(ic,1)).']
countCell =
'cat' 'dog'
[ 2] [ 1]
FYI, you can later extract the counts via counts = [countCell{2,:}];.
If you wan to do it without the help of these functions, you can fix up your myACsort function as follows:
function answer = myACsort(input)
a = sort(input); % sort operates on cell arrays of strings
i = 1; count = 1;
uwords = a(1);
while (i<numel(a))
if i<numel(a) && isequal(a{i},a{i+1})
a(i+1) = [];
count(i) = count(i)+1;
else
i=i+1;
count(i) = 1;
uwords(i) = a(i);
end
end
answer = [uwords(:).'; num2cell(count(:)).'];
Although array growing is not very efficient.
Another approach: sort the strings (variable sortedStrs), detect the end of each run of equal strings in the sorted sequence (variable ind), and the result is easily obtained from that.
strs = {'cat','dog','cat'}; %// data
n = numel(strs);
sortedStrs = sort(strs);
dif = arrayfun(#(n) ~strcmp(sortedStrs{n},sortedStrs{n-1}), 2:n);
ind = [ find(dif) n ];
result(1,:) = sortedStrs(ind);
result(2,:) = mat2cell([ind(1) diff(ind)],1,ones(1,numel(ind)));