1

みなさん、

テキストファイルをMATLABに解析しようとしています。これは、文字列(変数)と値(前の変数に関連付けられている)が割り当てられたいくつかのブロック(START_BLOCK / END_BLOCK)で構成されています。

例はこれです:

START_BLOCK_EXTREMEWIND
velocity_v1 29.7


velocity_v50    44.8


velocity_vred1  32.67
velocity_vred50 49.28


velocity_ve1    37.9



velocity_ve50   57


velocity_vref   50



END_BLOCK_EXTREMEWIND

現在、私のコードは次のとおりです。

fid = fopen('test_struct.txt','rt');
C = textscan(fid,'%s %f32 %*[^\n]','CollectOutput',true);
C{1} = reshape(C{1},1,numel(C{1}));
C{2} = reshape(C{2},1,numel(C{2}));



startIdx = find(~cellfun(@isempty, regexp(C{1}, 'START_BLOCK_', 'match')));
endIdx = find(~cellfun(@isempty, regexp(C{1}, 'END_BLOCK_', 'match')));
assert(all(size(startIdx) == size(endIdx)))
extract_parameters = @(n)({C{1}{startIdx(n)+1:endIdx(n) - 1}});
parameters = arrayfun(extract_parameters, 1:numel(startIdx), 'UniformOutput', false);

s = cell2struct(cell(size(parameters{1})),parameters{1}(1:numel(parameters{1})),2);

s.velocity_v1 = C{2}(2);
s.velocity_v50 = C{2}(3);
s.velocity_vred1 = C{2}(4);
s.velocity_vred50 = C{2}(5);
s.velocity_ve1 = C{2}(6);
s.velocity_ve50 = C{2}(7);
s.velocity_vref = C{2}(8);

動作しますが、完全に静的です。私はむしろ次のことができるコードが欲しいです:

1. check the existence of blocks --> as already implemented;
2. the strings are to be taken as fields of the structure;
3. the numbers are meant to be the attributes of each field.

最後に、複数のブロックがある場合は、構造全体を取得するために、それらのブロックについて反復する必要があります。構造コーディングに取り組むのは初めてですので、しばらくお待ちください。

よろしくお願いします。

よろしくお願いします。

4

2 に答える 2

1

動的なフィールド名を利用したいと思うようです。フィールドの名前を格納し、このフィールドに設定する値を保持する構造体がある場合は、次の構文を使用して割り当てを実行できますsfieldNamefieldVal

s.(fieldName) = fieldVal;

このMATLABドキュメントには、詳細情報が記載されています。

これを念頭に置いて、テキストを解析するために少し異なるアプローチを取りました。forループを使用してテキストを繰り返し処理しました。forループはMATLABで時々眉をひそめますが(MATLABはベクトル化された操作用に最適化されているため)、この場合、コードをよりクリーンにするのに役立つと思います。さらに、私の理解では、を使用する必要がある場合、arrayfunこれをforループに置き換えても、とにかくパフォーマンスに大きな影響を与えることはおそらくないでしょう。

次のコードは、テキスト内の各ブロックを、指定されたフィールドと値を持つ構造体に変換します。これらの結果の「ブロック」構造体は、上位レベルの「結果」構造体に追加されます。

fid = fopen('test_struct.txt','rt');
C = textscan(fid,'%s %f32 %*[^\n]','CollectOutput',true);
fclose(fid);

paramNames = C{1};
paramVals = C{2};

curBlockName = [];
inBlock = 0;
blockCount = 0;

%// Iterate through all of the entries in "paramNames".  Each block will be a
%// new struct that is then added to a high-level "result" struct.
for i=1:length(paramNames)
    curParamName = paramNames{i};
    isStart = ~isempty(regexp(curParamName, 'START_BLOCK_', 'match'));
    isEnd = ~isempty(regexp(curParamName, 'END_BLOCK_', 'match'));

    %// If at the start of a new block, create a new struct with a single
    %// field - the BlockName (as specified by the text after "START_BLOCK_"
    if(isStart)
        assert(inBlock == 0);
        curBlockName = curParamName(length('START_BLOCK_') + 1:end);
        inBlock = 1;
        blockCount = blockCount + 1;
        s = struct('BlockName', curBlockName);          

    %// If at the end of a block, add the struct that we've just populated to
    %// our high-level "result" struct.
    elseif(isEnd)
        assert(inBlock == 1);
        inBlock = 0;
        %// EDIT - storing result in "structure of structures"
        %//  rather than array of structs
        %// s_array(blockCount) = s;
        result.(curBlockName) = s;

    %// Otherwise, assume that we are inside of a block, so add the current
    %// parameter to the struct.
    else
        assert(inBlock == 1);
        s.(curParamName) = paramVals(i);
    end
end

%// Results stored in "result" structure

うまくいけば、これはあなたの質問に答えます...または少なくともいくつかの役立つヒントを提供します。

于 2012-09-06T03:44:42.507 に答える
0

私は今日コードを編集しましたが、今ではほぼ意図したとおりに機能します。

clc, clear all, close all

%Find all row headers
fid = fopen('test_struct.txt','r');
row_headers = textscan(fid,'%s %*[^\n]','CommentStyle','%','CollectOutput',1);
row_headers = row_headers{1};
fclose(fid);

%Find all attributes
fid1 = fopen('test_struct.txt','r');
attributes = textscan(fid1,'%*s %s','CommentStyle','%','CollectOutput',1);
attributes = attributes{1};
fclose(fid1);

%Collect row headers and attributes in a single cell
parameters = [row_headers,attributes];


%Find all the blocks
startIdx = find(~cellfun(@isempty, regexp(parameters, 'BLOCK_START_', 'match')));
endIdx = find(~cellfun(@isempty, regexp(parameters, 'BLOCK_END_', 'match')));
assert(all(size(startIdx) == size(endIdx)))


%Extract fields between BLOCK_START_ and BLOCK_END_
extract_fields = @(n)(parameters(startIdx(n)+1:endIdx(n)-1,1));
struct_fields = arrayfun(extract_fields, 1:numel(startIdx), 'UniformOutput', false);

%Extract attributes between BLOCK_START_ and BLOCK_END_
extract_attributes = @(n)(parameters(startIdx(n)+1:endIdx(n)-1,2));
struct_attributes = arrayfun(extract_attributes, 1:numel(startIdx), 'UniformOutput', false);


for i = 1:numel(struct_attributes)
    s{i} = cell2struct(struct_attributes{i},struct_fields{i},1);
end

さて、最終的に、私は、たとえば、私の要件を満たすことができる構造のセルを取得します。私が改善したい唯一のポイントは次のとおりです。

- Give each structure the name of the respective block.

誰かが貴重なヒントを持っていますか?

応援してくれてありがとう。

よろしく、フランチェスコ

于 2012-09-06T12:19:25.107 に答える