大家好,
我正在嘗試構建一個包含多個列錶框的對話框窗口,每個列錶框包含數據表中相應列的所有值。 在任何列表中選擇一個或多個項目後,我希望根據該選擇過濾剩餘列表中的項目。 我已經實現了我剛才在下面描述的內容,但事情是這樣的:如果我在循環中填充對話框窗口,而不是使用整數對列表子集索引進行硬編碼,如下所示,則使用當時i 的當前值調用該函數執行而不是在循環中創建列錶框時所採用的值。 我已閱讀腳本指南並嘗試了幾個選項,包括 Eval( Eval Expr( Expr())) 和 Eval Substitute( Expr(), Expr())) 但我無法讓它工作。 我現在正在將整個表達式構建為循環中的長字符串,並對其進行 Eval( Parse()) 處理,但這看起來很愚蠢。 有人可以幫我解決這裡的正確語法嗎?
謝謝,
約翰
Names Default To Here( 1 );
If( !Namespace Exists( "fq" ),
New Namespace(
"fq"
)
);
dt = New Table( "Sample data",
Add Rows( 9 ),
New Column( "id",
Character,
"Nominal",
Set Values( {"a", "a", "a", "b", "b", "b", "c", "c", "c"} )
),
New Column( "value",
Character,
"Nominal",
Set Values( {"A", "B", "C", "D", "E", "F", "G", "H", "I"} )
),
New Column( "val2",
Character,
"Nominal",
Set Values( {"one", "two", "three", "one", "two", "three","one", "two", "three"} )
)
);
filterSelected = Function( {dt, values, index},
/*
Sorts displayed values in all list boxes based on selection
*/
columns = fq:filterColumns;
filters = fq:filters;
selectedColum = Remove From( columns, index )[1];
selctedFilter = Remove From( filters, index )[1];
rows = dt << Get rows where( Contains( values, as Column( dt, selectedColum ) ) );
// If nothing is selcted, all values should be chosen
If(Length(values)==0,
rows = dt << get rows where(!Ismissing(As Column(dt, selectedColum)))
);
// Set list items according to selection
Local( {j = 1},
For( j = 1, j <= N Items( filters ), j++,
filters[j] << Set items( Column( dt, columns[j] )[rows] )
)
);
);
getSelection = Function( {},
Local( {j =1},
For( j=1, j <= N Items(fq:filters), j++,
print(fq:filterColumns[j], fq:filters[j] << get items());
);
);
);
nestedFilters = Function( {filtercolumns},
fq:filtercolumns = filtercolumns;
dialog = New Window( "Fetch rows matching:",
Show Menu( 0 ),
show toolbars( 0 ),
Border Box( Top( 20 ), Bottom( 20 ), Left( 10 ), Right( 10 ),
V List Box(
Align( right ),
filter_boxes = V List Box(),
H List Box(
ok_button = Button Box( "OK" ),
cancel_button = Button Box( "Cancel", dialog << close window )
)
)
),
ok_button << Set function(
getSelection();
dialog << close window;
)
);
fq:filters = {};
fq:all_rows = {};
//for(i=1, i<=N Items(filtercolumns), i++,
filter_boxes << append( Text Box( fq:filtercolumns[1], <<SET font="" style=""></SET>再次感謝。 我看起來我會堅持使用 eval(parse()) ,儘管它看起來確實有點像黑客。 但無論如何感謝您的見解!
如果存在 i==4 值,則必須有一個 i 未包裝在 expr() 中。
Parse 與 EvalExpr 的權衡:
- parse 生成的字符串在編輯器中沒有突出顯示語法,但下一個維護代碼的人可能會理解它。 在您的示例中,如果可能有 100 個串聯,我可能會將 eval-parse 放入循環內。
- evaexpr 可能比 parse 更快,但對於一個小例子來說沒有真正的區別。 如果您要通過串聯構建一百萬個字符的字符串,那麼它可能很重要。 Evalexpr 需要一條註釋來告訴下一個維護者它在做什麼。
還有其他更強大且更難以解釋和維護的表達式操作方法;我認為對於這個例子來說,其中任何一個都是合理的。 (arg、narg、head、insertinto、substituteinto、... 我每次都必須重新學習這些。)
我能做的就是這個,但這似乎...... 我猜是愚蠢的...
expression = "";
for( i = 1, i <= N Items( fq:filtercolumns ), i++,
expression = expression ||
"filter_boxes << append( Text Box( fq:filtercolumns[" || char(i) || "], <<SET font="" style=""></SET>感謝您嘗試一下! 不幸的是,我遇到了與過去相同的問題:當我在列表中進行選擇時,如果 i (即 4),則使用當前值調用 filterSelected 函數,從而導致下標範圍錯誤。

嘗試這個
for( i = 1, i <= N Items( filtercolumns ), i++,
eval(
evalexpr(
filter_boxes << append( Text Box( fq:filtercolumns[Expr( i )], <<SET font="" style=""></SET>我使用了“1”的情況,將 1 更改為 expr(i),將其放入 i 循環內的 eval/evaexpr 內。
編輯:並且提出了很好的問題!