Postgres get entire array from multidimensional array - postgresql

I'd like to do the following:
CREATE TABLE example ( name text, arr text[][]);
INSERT INTO example VALUES ( 'aa', '{}');
UPDATE example SET arr = arr || ARRAY['header'] WHERE name = 'aa';
Right here, I have arr = [['header']]. I can easily add another array making it arr = [['header'], ['another']] by calling the last line from above again with 'another' inside the array constructor. However, I'm looking to add elements to those inner arrays now. Something like...
UPDATE example SET version[1] = version[1] || ARRAY['more'] WHERE name = 'aa'
However, postgres throws the error, wrong number of subscripts. I understand that postgres multidimensional arrays must have the same dimensions inside, so I would have to be able to add an element to all the inner arrays at once (probably NULL) and then change the one I'm adding to. Is there any way to do this without some kind of loop?

Related

Concatenating (sub)fields of structs in a cell array

I have a Matlab object, that is a cell array containting structs that have almost identical structures and I want to programmatically get a (sub)field of the structs of all cell array elements.
For example, we take test
test = {struct('a',struct('sub',1)), struct('a',struct('sub',2),'b',1)};
This will create a cell array with the following structure:
cell-element 1: a --> sub --> 1
cell-element 2: a --> sub --> 2
\-> b --> 1
It can be seen that the elements of test don't have the exact same structure, but similar. How can I get all values of the a.sub fields of the elements of the cell. I can obtain them in this specific problem with
acc=zeros(1,numel(test));
for ii=1:numel(test)
acc(ii) = test{ii}.a.sub;
end
but I can't quite get this method to work in a more general context (ie. having different fields).
You may want to use the function getfield:
%//Data to play with
test = {struct('a',struct('sub',1)), struct('a',struct('sub',2),'b',1)};
%//I'm interested in these nested fields
nested_fields = {'a', 'sub'};
%//Scan the cell array to retrieve the data array
acca = cellfun(#(x) getfield(x, nested_fields{:}), test);
In case your data cannot guarantee that all the elements are the same type and size, then you need to output a cell array instead:
%//Scan the cell array to retrieve the data cell array
accc = cellfun(#(x) getfield(x, nested_fields{:}), test, 'UniformOutput', false);
Later Edit
If one wants to use different sets of nested fields for each cell element then:
%//nested_fields list should have the same size as test
nested_fields = {{'a','sub'}, {'b'}};
accm = cellfun(#(x,y) getfield(x,y{:}), test, nested_fields, 'UniformOutput', false);
Edit: No need for recursion, as shown by #CST-link:s answer; the native getfield function can neatly unfold a cell array of fields as its second argument, e.g. getfield(foo{i}, fields{:}) instead of the call to the recursive function in my old answer below. I'll leave the recursive solution below, however, as it could have some value in the context of the question.
You can build you own recursive version of getField, taking a cell array of fields.
function value = getFieldRec(S,fields)
if numel(fields) == 1
value = getfield(S, fields{1});
else
S = getfield(S,fields{1})
fields{1} = [];
fields = fields(~cellfun('isempty',fields));
value = getFieldRec(S,fields);
end
end
Example usage:
foo = {struct('a',struct('sub',1)), ...
struct('a',struct('sub',2),'b',3), ...
struct('c',struct('bar',7),'u',5)};
accessFields = {'a.sub', 'b', 'c.bar'};
values = zeros(1,numel(foo));
for i = 1:numel(foo)
fields = strsplit(accessFields{i},'.');
values(i) = getFieldRec(foo{i},fields);
end
With the following result
values =
1 3 7
I have found a way to do this using eval:
function out = catCellStructSubField(cellStruct, fieldName)
out = zeros(1,numel(cellStruct));
for ii = 1:numel(cellStruct)
out(ii) = eval(['cellStruct{ii}.' fieldName]);
end
Where it can be used on my test example like this:
catCellStructSubField(test, 'a.sub')
Dynamic field names (cellStruct{ii}.(fieldName)) does not work because I'm accessing sub-fields.
I know eval is often a bad idea. I'm curious for different solutions.

How do I use containers.Map in Matlab with a cell array as the keys and a vector of integers as the values

I have a cell array that contains words like 'a', 'b', and 'c' for example. What I want to be able to do is use Matlab's containers.Map to make a hash table that I can add values to for each key and be able to look them up quickly. I am able to do this if I do not initialize my containers.Map object beforehand as follows but it does not allow me (or at least I haven't found a way) to add more key/value pairs later and makes it so that I have to reinitialize the object during each iteration of a loop:
key = {'a','b','c'};
newmap = containers.Map(key,[1,2,3]);
My problem is that I need to be able to continually add new keys to the hash table and therefore cannot keep initializing the containers.Map object each time, I want one long hash table with all the keys and values that I get while in a loop.
Here is the code that I am trying to get working, I want to be able to add the keys to the containers.Map object newmap and their corresponding values at the same time. The keys are always strings in a cell array and the values are always integers:
key = {'a','b','c'};
val = [1,2,3];
newmap = containers.Map(); % containers.Map object initialization
newmap(key) = val;
My desired output would something like this:
newmap(key)
ans = 1 2 3
Attempts at solving this:
I have tried converting the cell array of keys using cellstr() and char() but haven't had any luck with these. I seem to keep getting this error when trying this:
Error using containers.Map/subsref
Specified key type does not match the type expected for this container.
Thanks for any help.
% Initialize
map = containers.Map('KeyType','char','ValueType','double');
% Assume you get these incrementally
key = {'a','b','c'};
val = [1,2,3];
% Add incrementally
for ii = 1:numel(key)
map(key{ii}) = val(ii);
end
You can retrieve all values at once for a given set of keys, but you will get a cell array. No way around it, but you can convert with cell2mat(), or retrieve incrementally with a loop map(key{ii})
% Retrieve all
values(map,key)
ans =
[1] [2] [3]

Make a MatLab table out of 2 Cell Array

What is the most efficient way to generate a table from 2 cell arrays. Array A contains data and Array B contains the corresponding names. I would like to combine them into a convenient table structure.
Cell_Array_A =
{[10x10],[10x10],[];
[10x11],[],[10x12];
[9x10],[13x10],[]}
Cell_Array_B =
{['A','B',[];
'B',[],'A';
'B','A',[]}
It should generate a table with the headers 'A' and 'B'. However, in my real data set, I have a lot of variable names, which I don't know. So I need a way to read all variables from the first row and use them to create the table for the rest of the matrix.
Example of the desired output:
'A' 'B'
[10x10] [10x10]
[10x12] [10x11]
[13x10] [9x10]
I tried so far to process the arrays row wise to get rid of the empty arrays. However this is not very efficient. I run the following code for each row in Array A and B. Below an example for the first row in Array A which I later on use as the tablet for my table.
order_row = {};
order_row = Cell_Array_A(1,:);
ordered_filenames = order_row(~cellfun('isempty',order_row));
Edited answer The idea is 1) to collect the non-empty column headers, 2) for each unique column header collect the corresponding values:
% Unique variable names
nul_names = cellfun(#isempty,Cell_Array_B);
var_names = unique(Cell_Array_B(~nul_names));
% Function to find a column header index
ixhead = #(h,c) cellfun(#(x) isequaln(x,h), c(:));
% Collect the values
var_values = cellfun( ...
#(h) Cell_Array_A(ixhead(h, Cell_Array_B)), var_names, ...
'UniformOutput', false ...
);
% Create the table
tbl = table(var_values{:}, 'VariableNames', var_names);

How to Compare the same Char Value in a Cell Array 1x1 with If Else Sentence

First i do my connection and assign the names for table, columns, rows...
conn = database('db', 'user', 'pass');
Then i make a query, for select in the data base an Varchar
curs = exec(conn, 'select row/column from table');
I request the Data
curs = fetch(curs);
AA = curs.Data;
then my problem begin... I'll add a variable with the name 'Alex', to find the same name in my database to the assigned column and use the if statement to verify their existence..
var = 'Alex';
then I wonder what is the best choice to retrieve the data and make a comparison between the database and my Variable:
index = find(strcmp(AA,var));
or
data = strfind(AA,var);
and my structure for the if statement is this:
if AA == var
msgbox('Data Exist')
end
this doesn't work for me, i just receive "Undefined function 'eq' for input arguments of type 'cell'."
So, I'm assuming you have something like:
var = 'Alex';
AA = {'Alex'};
Now, you can handle this in several ways, my favorite being:
isequal(var, AA{:})
The key point here is the {:} that extracts the content of the cell.
if var == AA{:} would work too, but only if var and AA{1} are the same length, otherwise it will cause an error. I would therefore not recommend using == for strings.
if AA is guaranteed to be a 1x1 cell array strcmp(var, AA{1}) or isequal({var}, AA)should work. However, if it can have more elements you can use ismember(var, AA).

assigning values to a field of an structure array in MATLAB

I want to replace the value of the fields in a structure array. For example, I want to replace all 1's with 3's in the following construction.
a(1).b = 1;
a(2).b = 2;
a(3).b = 1;
a([a.b] == 1).b = 3; % This doesn't work and spits out:
% "Insufficient outputs from right hand side to satisfy comma separated
% list expansion on left hand side. Missing [] are the most likely cause."
Is there an easy syntax for this? I want to avoid ugly for loops for such simple operation.
Credits go to #Slayton, but you actually can do the same thing for assigning values too, using deal:
[a([a.b]==1).b]=deal(3)
So breakdown:
[a.b]
retrieves all b fields of the array a and puts this comma-separated-list in an array.
a([a.b]==1)
uses logical indexing to index only the elements of a that satisfy the constraint. Subsequently the full command above assigns the value 3 to all elements of the resulting comma-separated-list according to this.
You can retrieve that the value of a field for each struct in an array using cell notation.
bVals = {a.b};
bVals = cell2mat( bVals );
AFAIK, you can't do the same thing for inserting values into an array of structs. You'll have to use a loop.