我正在使用一個雜亂的手動維護“資料庫”,該資料庫有一列包含帶有名稱、值對的字串。我正在嘗試使用正則運算式決議整個列以提取值。該列很大(> 100,000 個條目)。作為我實際資料的代理,讓我們使用以下代碼:
line1={'''thing1'': ''-583'', ''thing2'': ''245'', ''thing3'': ''246'', ''morestuff'':, '''''};
line2={'''thing1'': ''617'', ''thing2'': ''239'', ''morestuff'':, '''''};
line3={'''thing1'': ''unexpected_string(with)parens5'', ''thing2'': 245, ''thing3'':''246'', ''morestuff'':, '''''};
mycell=vertcat(line1,line2,line3);
這捕獲了資料庫中遇到的一般問題。我想提取每行中的what thing1、thing2、 和thing3arecellfun用于輸出標量元胞陣列。它們通常應該是 3 位數字,但有時它們會有意想不到的形式。有時thing3完全沒有,名字甚至沒有出現在行中。有時會出現輕微的格式不一致,例如值周圍缺少單引號、缺少空格或三位數值前面出現破折號。我已經設法處理了所有這些,除了thing3完全丟失的情況。
我的一般方法是使用這樣的運算式:
expr1='(?<=thing1''):\s?''?-?([\w\d().]*?)''?,';
expr2='(?<=thing2''):\s?''?-?([\w\d().]*?)''?,';
expr3='(?<=thing3''):\s?''?-?([\w\d().]*?)''?,';
這在后面查找thingX'然后嘗試匹配:后跟零或一個空格,后跟 0 或 1 個單引號,后跟零或一個破折號,后跟字母、數字、括號或句點的任意組合(這被定義為token),使用延遲匹配,直到遇到零個或一個單引號,后跟逗號。我呼叫regexpasregexp(___,'tokens','once')回傳匹配的令牌。
問題是當沒有匹配項時,regexp 回傳一個空陣列。這使我無法使用,例如,
out=cellfun(@(x) regexp(x,expr3,'tokens','once'),mycell);
除非我用'UniformOutput',false. 問題是雙重的。首先,我需要手動查找不匹配的行。例如,我可以這樣做:
emptyout=cellfun(@(x) isempty(x),out);
emptyID=find(emptyout);
backfill=cell(length(emptyID),1);
[backfill{:}]=deal('Unknown');
out(emptyID)=backfill;
在這個例子中,emptyID長度為 1,所以這段代碼有點矯枉過正。但我相信這是對更長的時間進行概括的正確方法。此代碼將out使用 string更改每個空元胞陣列Unknown。但這會導致第二個問題。我現在有一個“凌亂”的非標量值元胞陣列。例如,我無法檢查unique(out)結果。
恕我啰嗦,但我想舉一個清楚的例子來說明這個問題。現在我的實際問題分為幾個部分:
- 有沒有辦法在不使用的情況下完成我想要做的事情
'UniformOutput',false?例如,有沒有辦法在regexp沒有匹配的情況下傳遞自定義字串(例如,'Unknown'如果沒有匹配則傳遞)?我可以想到一個“作弊”,即|在運算式中使用運算子,如果第一個標記不匹配,則查找始終找到的內容。然后我仍然需要重復輸出并將該結果的每個實體更改為'Unknown'. - 如果我采用這種
'UniformOutput',false方法,我怎樣才能在最后恢復標量單元陣列以輕松操作它(例如通過它unique)?我承認我不是 100% 清楚標量和非標量單元陣列。 - 如果有一些我沒有想到的完全不同的方法,我也愿意接受。
- 相切的主要問題,我也使用單個運算式來運行試圖
regexp使用3-令牌拉出的值thing1,thing2和thing3在一次通過。'UniformOutput',false即使沒有空的結果,這似乎也需要regexp. 我不確定如何使用這種方法獲得標量單元陣列(例如 Nx1 單元陣列,其中每個單元都是 3x1 單元)。
歸根結底,我想使用這些結果構建一個表:
mytable=table(out1,out2,out3);
編輯:使用可以celldisp說明問題:
celldisp(out)
out{1}{1} =
246
out{2} =
Unknown
out{3}{1} =
246
我假設我需要更改 的結構,out以便out{1}{1}and的內容out{3}{1}只是out{1}and out{3}。但是如果需要,我不確定如何完成此操作'UniformOutput',false。
uj5u.com熱心網友回復:
注意:我沒有使用過 MATLAB,這并不能回答“高效”方面的問題,但是......
強制總是匹配怎么樣?
只是想想你真的想要一個匹配來跳過這個問題,一個空匹配怎么樣?
在此處查看MATLAB 幫助頁面,我可以看到一個'emptymatch'選項,也許可以嘗試一下。
例如
the_thing_i_want_to_find|
匹配“the_thing_i_want_to_find”或空匹配,注意|字符。
在捕獲組中,它可能如下所示:
(the_thing_i_want_to_find|)
uj5u.com熱心網友回復:
作為一種解決方法,我發現 usingregexprep可用于查找thing3缺少的條目。例如:
replace='$1 ''thing3'': ''Unknown'', ''morestuff''';
missingexpr='(?<=thing2'':\s?)(''?-?[\w\d().]*?''?,) ''morestuff''';
regexprep(mycell{2},missingexpr,replace)
ans =
''thing1': '617', 'thing2': '239', 'thing3': 'Unknown', 'morestuff':, '''
將其應用于整個陣列:
fixedcell=cellfun(@(x) regexprep(x,missingexpr,replace),mycell);
out=cellfun(@(x) regexp(x,expr3,'tokens','once'),fixedcell,'UniformOutput',false);
這感覺有點迂回,但它有效。
uj5u.com熱心網友回復:
cellfun可以用普通的舊 for 回圈替換。您的代碼要么同樣快,要么甚至更快。cellfun無論如何都是用回圈實作的,除了更少的代碼行之外,使用它沒有任何好處。在您的顯式回圈中,您可以檢查 的輸出regexp,并以您喜歡的任何方式構建您的輸出陣列。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/363402.html
上一篇:繞單位圓旋轉線到任意位置
