构建可搜索对象的最快方法,该对象将字符串与数字

时间:2017-03-10 20:51:07

标签: matlab

我试图在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),但速度非常慢。

2 个答案:

答案 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}}很多。