我试图在MATLAB中将字符串与数字相关联。也就是说,我想创建一个采用
形式的对象string: 'abcd', index: 1
string: 'abdd', index: 2
etc.
问题是,我需要能够在提供字符串时搜索对象,例如'abcd'并让它返回关联的(唯一)索引,在这种情况下为1。我还需要能够使用索引搜索对象并让它返回关联的字符串。需要相当频繁地将新元素添加到此对象。此对象中将有许多元素(大约500000)。字符串本身一般不是“有序的”(如果这样的话甚至会有帮助的话)。
问题:在MATLAB中执行此操作的最快方法是什么?
我尝试了什么:看起来MATLAB中的Map类是相关的;但是,我无法弄清楚如何在两个方向上搜索。我在Mathworks网站上提供的示例中说明了这一点:
ticketMap = containers.Map(...
{'2R175', 'B7398', 'A479GY', 'NZ1452'}, ...
{'James Enright', 'Carl Haynes', 'Sarah Latham', ...
'Bradley Reid'});
ticketMap('2R175') -> returns James Enright
但似乎不支持向另一个方向搜索,也就是说,鉴于'James Enright'让它返回'2R175'。我也尝试了Map2代码(http://www.mathworks.com/matlabcentral/fileexchange/40323-map2-enhanced-map-class),但速度非常慢。
答案 0 :(得分:4)
我认为最好的解决方案是构建两个地图,一个是从故障单到地图的映射,另一个是从名称到故障单的映射。
示例:
tickets = {'2R175', 'B7398', 'A479GY', 'NZ1452'};
names = {'James Enright', 'Carl Haynes', 'Sarah Latham', 'Bradley Reid'};
ticketMap = containers.Map(tickets, names);
namesMap = containers.Map(names, tickets);
%ticketMap('2R175') -> returns James Enright
%namesMap('James Enright') -> 2R175
创建和管理两个地图可能会浪费内存和计算时间,但time-time complexity,它是最有效的解决方案。
答案 1 :(得分:1)
我认为最快的解决方案是一个具有有限错误检查的对象,它保留了字符数组的单元格数组和相关的索引数组。然后,可以使用简单索引和strcmp
的组合来拉动 - 或根据需要。
这是一个关于这样一个对象的快速例子(使用词汇闭包,因为我喜欢它们并且过去看到了更好的表现,这些日子可能不是这样)。
function store = makeStringMap(strings)
if (nargin >= 1) && not(isempty(strings))
if iscellstr(strings)
strings = strings(:);
elseif ischar(strings)
strings = cellstr(strings);
else
error('makeStringStore:wrongInputType',...
'First input ''strings'' must be either a cellstr or a char array.');
end
else
strings = {};
end
nstrings = numel(strings);
indices = 1:nstrings;
store.append = @(string) append(string);
function [] = append(string)
if ischar(string)
string = cellstr(string);
end
nstring = numel(string) ;
strings = [strings;string] ;
indices = [indices,(1+nstrings)+(0:(nstring-1))] ;
nstrings = indices(end) ;
end
store.getStringByIndex = @(index) getStringByIndex(index);
function string = getStringByIndex(index)
if all(index>0 && index<=nstrings)
string = strings(index);
end
end
store.getIndexByString = @(string) getIndexByString(string);
function index = getIndexByString(string)
if ischar(string)
string = cellstr(string);
end
nstring = numel(string);
index = zeros(nstring,1);
for k = 1:nstring
index = indices(strcmp(strings,string{k}));
end
end
store.getStrings = @() getStrings();
function out = getStrings()
out = strings;
end
end
简单的测试运行:
>> s = makeStringMap(char(randi([97,122],5,10)));
>> s.getStrings()
ans =
'yheepozpvs'
'kkdrslqcic'
'smktndqhjg'
'nfqikjtsbb'
'jpfgtdlbem'
>> s.getStringByIndex(2)
ans =
'kkdrslqcic'
>> s.getIndexByString(s.getStringByIndex(2))
ans =
2
>> s.append(char(randi([97,122],3,10)));
>> s.getStringByIndex(7)
ans =
'tajrjqmikg'
>> s.getIndexByString(s.getStringByIndex(7))
ans =
7
我会注意到虽然我经常使用变量string
,但它不是新的string
类,因为我正在运行R2016a但仍然使用char
和{{ 1}}很多。