Structure Indexing to Find Words

1 vue (au cours des 30 derniers jours)
Russell Marki
Russell Marki le 20 Mar 2018
Commenté : Russell Marki le 21 Mar 2018
clear
load('dict_perms.mat')
dict=6;
dict_perms=dict_perms{6};
dict_char=char(dict_perms+64);
dict_size=length(dict_perms(:,1));
for i=1:dict_size
dict_lex.(dict_char(i,1)).(dict_char(i,2)).(dict_char(i,3)).(dict_char(i,4)).(dict_char(i,5)).(dict_char(i,6))=uint16(i);
end
%the next letters possible from a series of letters can be found with
letters=fieldnames(dict_lex.('A').('B').('H'));
%I want words from possible letters
%like dict_lex.(['A','B']).(['D','B']).(['F','H']).(['O','F']).(['R','M']).(['S','K'])
%could be found with a for loop but it is too time consuming
fieldnames(dict_lex.('A'));
fieldnames(dict_lex.('B'));
I need to find all possible words that have letters in certain parts of the word. This could be done with a for loop but that is too time consuming. Can anyone point me in the right direction?
  1 commentaire
Stephen23
Stephen23 le 21 Mar 2018
"I need to find all possible words that have letters in certain parts of the word."
This is trivial with regular expressions. See my answer.

Connectez-vous pour commenter.

Réponse acceptée

Stephen23
Stephen23 le 21 Mar 2018
Modifié(e) : Stephen23 le 21 Mar 2018
Dynamically accessing the fieldnames of nested structures is likely to be a very inefficient solution, and is far too complex for the task. You would be much better off simply accessing the data directly from the char array using logical indexing, or converting to a cell array of char vectors and then using standard, efficient built-in tools such as regular expressions, or even strncmp. For example:
>> DC = char(dict_perms{6}+64);
>> idx = DC(:,1)=='A' & DC(:,2)=='B' & DC(:,3)=='H';
>> DC(idx,:)
ans = ABHORS
To match multiple character you could add more logical conditions to the index:
>> idx = ...
(DC(:,1)=='A' | DC(:,1)=='B') & ...
(DC(:,2)=='B' | DC(:,2)=='D') & ...
(DC(:,3)=='H' | DC(:,3)=='F') & ...
(DC(:,4)=='O' | DC(:,4)=='F') & ...
(DC(:,5)=='R' | DC(:,5)=='M') & ...
(DC(:,6)=='S' | DC(:,6)=='K');
>> DC(idx,:)
ans = ABHORS
But actually it would be much easier and more versatile to use regular expressions:
>> DS = cellstr(DC);
>> idx = ~cellfun('isempty',regexp(DS,'^[AB][DB][FH][OF][RM][SK]','once'));
>> DC(idx,:)
ans = ABHORS
It is easy with regular expressions to return the complete matching words, the matching letters, their indices, or the trailing letters... it all depends on what you want. If you give a more accurate description of the data that you need then I can help you with the regular expression.
  2 commentaires
Guillaume
Guillaume le 21 Mar 2018
I agree with Stephen. This is exactly the sort of job regular expressions are designed for and it's unlikely you'll be able to write something more efficient. regular expression engines are highly optimised.
An alternative to storing the words as a 2d char array or a cell array of 1d char array would be to store them as a string array, which overall is a lot easier to manipulate. To convert the whole dict_perms in a cell array of string arrays:
dict_lex = cellfun(@(c) string(char(c+64)), dict_perms, 'UniformOutput', false)
Russell Marki
Russell Marki le 21 Mar 2018
Thanks, this is exactly what I am looking for.

Connectez-vous pour commenter.

Plus de réponses (1)

KSSV
KSSV le 21 Mar 2018
T = table(dict_char) ;
T = table2cell(T) ;
idx = strfind(T,'A') ;
Read about strfind. If you convert your character array to cell, you can use certain functions and make the code run faster.
  1 commentaire
Russell Marki
Russell Marki le 21 Mar 2018
If I want all the words that begin with 'A' or 'B', have a second letter of 'D' or 'B', have a third ... . Right now I have a fairly quick way to do this, but I have a need for speed.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Data Type Conversion dans Help Center et File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by