回覆:挑戰 5 – 結果@ErraticAttack - 好的!
回覆:挑戰 5 – 結果謝謝@ErraticAttack 。我喜歡你的做法!
回覆:挑戰 5 – 結果只是在這裡添加我的兩分錢,因為我正在建立一些函數式程式設計類型的輔助函數。
根據我的經驗,很容易變得有點忘乎所以並建立一個過於複雜的解決方案,既有點慢又有點難以理解。
因此,這是一個快速簡單的映射/過濾/減少的實現,它幾乎與內建方法(循環或直接內建呼叫)一樣快,並且具有不需要使用 Expr(...) 函數的額外好處來利用它們。
map = Function( {inputs/* list, function*/},
/* uses a single underscore _ as the wild-card */
{__i__, __result__, __list__, _},
__result__ = {};
__list__ = Arg( inputs, 1 );
Eval(
Substitute(
Expr(
For( __i__ = N Items( __list__ ), __i__ > 0, __i__--,
Insert Into( __result__, _ = __list__[__i__]; __function__, 1 )
)
)
,
Expr( __function__ ), Arg( inputs, 2 )
);
);
__result__
);
reduce = Function( {inputs/*list, function, seed = 0*/},
/* uses a single underscore for current item, 'acc' for current value */
{__i__, __list__, _, acc = 0},
If( N Items( inputs ) == 3,
acc = Arg( inputs, 3 )
);
__list__ = Arg( inputs, 1 );
Eval(
Substitute(
Expr(
For( __i__ = N Items( __list__ ), __i__ > 0, __i__--,
_ = __list__[__i__];
acc = __function__
)
)
,
Expr( __function__ ), Arg( inputs, 2 )
)
);
acc
);
filter = Function( {inputs/*list, filter = _*/},
/* uses a single underscore _ for current item */
{__i__, __list__, __result__, _filter_, _},
__result__ = {};
If( N Items( inputs ) == 1,
_filter_ = Expr( _ )
,
_filter_ = Arg( inputs, 2 )
);
__list__ = Arg( inputs, 1 );
Eval(
Substitute(
Expr(
For( __i__ = N Items( __list__ ), __i__ > 0, __i__--,
_ = __list__[__i__];
If( __filter__,
__result__[N Items(__result__) + 1] = _
)
)
)
,
Expr( __filter__ ), Name Expr( _filter_ )
);
);
Reverse( __result__ )
);
filter({{1, 0, 2, Empty(), 3, .}});
lst = repeat( {{1, "a"}, {2, "b"}, {3, "c"}, {4, "d"}}, 10000 );
start = HP Time();
a = filter({lst, _[1] < 3} );
end = HP Time();
Write( "\!NMy Method: ", (end - start) / 1000000 );
reduce( {{"a", "b", "c"}, Uppercase( _ || acc ), seed = ""} );
list = Repeat( {Random Integer( 1, 100000000 )}, 50000 );
start = HP Time();
Show( reduce( {list, If( _ > acc, _, acc)} ) );
end = HP Time();
Write( "\!NMy Method: ", (end - start) / 1000000 );
start = HP Time();
Show( Max( list ) );
end = HP Time();
Write( "\!NBuiltin Method: ", (end - start) / 1000000 );
start = HP Time();
Show( reduce( {list, acc + _} ) );
end = HP Time();
Write( "\!NMy Method: ", (end - start) / 1000000 );
start = HP Time();
Show( Sum( list ) );
end = HP Time();
Write( "\!NBuiltin Method: ", (end - start) / 1000000 );
strings = Repeat( {"abcdefg"}, 1e5 ); // about a second
start = Tick Seconds();
substrings1 = map( {strings, Substr( _, 1 + 2, 1 )} );
stop = Tick Seconds();
Write( "\!n applyfunction time: ", stop - start );
start = Tick Seconds();
substrings2 = {};
For( i = N Items( strings ), i > 0, i--,
Insert Into( substrings2, Substr( strings[i], 3, 1 ), 1 )
);
stop = Tick Seconds();
Write( "\!n JSL loop time: ", stop - start );
If( substrings1 == substrings2,
Write( "\!nOK" ),
Write( "\!noops" )
);當我在我的(相當慢的)筆記型電腦上運行它時,我得到以下輸出:
/*<BR />My Method: 0.152577
reduce({list, If(_ > acc, _, acc)}) = 99994198;
My Method: 0.056897
Max(list) = 99994198;
Builtin Method: 0.024798
reduce({list, acc + _}) = 2495626010963;
My Method: 0.04259
Sum(list) = 2495626010963;
Builtin Method: 0.007765
applyfunction time: 0.166666666656965
JSL loop time: 0.0500000000029104
OK<BR />*/請注意,使用reduce 函數查找位元清單(50,000 個條目)中的最大數字僅花費內建Max() 呼叫的約2 倍時間,而相同清單的總和則慢約6 倍。考慮到 Map/Reduce/Filter 函數增加的靈活性,這些數字相當不錯。
回覆:挑戰 5 – 結果謝謝@唐麥考馬克取得 MFR 的連結。 我不想破壞任何(近期)未來的公告,但是是的,它即將到來...
回覆:挑戰 5 – 結果謝謝@唐麥考馬克為了詳細的寫法! 這個挑戰讓我想起了偉大的事情MFR:用於列表/關聯數組操作的 JSL 函數程式庫乙y @nascif_jmp 。 希望其中一些構造有一天能夠進入 JSL 的基本函數中。
挑戰 5 – 結果對於這篇文章的延遲,我深表歉意。 除此之外,我一直非常忙於準備關於函數式資料瀏覽器的演講在JMP探索高峰會。 看來常規貢獻者同樣全神貫注,因為我只收到了兩份針對此挑戰的非工作人員提交的資料。
以下是第五次挑戰後的總得分:
說到探索高峰會,我的同事史丹·科普羅夫斯基正在組織JMP 腳本取消會話。 請點擊連結了解更多詳情;我們很高興在那裡見到你。
在挑戰 5 中,我要求你寫元函數,也就是函數的函數。 我的動機是採用只能應用於單一數字或字串的函數並擴展它們,以便它們可以應用於它們的複合值、向量和列表。 我發現這種類型的操作有些規律地發生,當 JSL 函數尚不存在時通常可以使用資料表公式來實現。 我希望在數據表之外也能使用此功能。
第 1 項和第 2 項應該相對簡單。 使用向量時,依賴 JSL 已透過預先存在的 JSL 函數或矩陣運算實現的功能會很有幫助。 計算中位數絕對偏差 (MAD) 最簡單的方法是一行程式碼:
中位數(絕對值(內維克- 中位數(內維克) ) )
在哪裡內維克是輸入向量。 此解決方案依賴於了解可以從內建 JSL 函數正確產生中位數。 該程式碼直接來自 MAD 的定義。
計算截尾平均值有點棘手,可以深入了解提供精確函數定義的重要性(稍後會詳細介紹)。 常見的方法是計算與下列項目相關的分位數之間界限值的平均值低百分比和百分比高,在哪裡低百分比和聚氯乙烯是挑戰 5 帖子中定義的參數。 例如:
loQ = 分位數(低百分比,內維克);
hiQ = 分位數(1-聚氯乙烯,內維克);
意思是(內維克[Loc(loQ <內維克< hiQ)]);
然而,該解決方案修剪了不多於低百分比從低值和不多於聚氯乙烯來自高價值。 因此,修剪的總百分比可能小於低電平+聚氯乙烯但再也不會了。 這種方法與發現的方法不一致分配平台不僅從兩個尾部均勻修剪,更重要的是,確保修剪的總百分比至少請求的金額(可能更多)。 以下程式碼產生與此定義一致的結果:
loRank = 上限(百分比*N行(內維克));
hiRank = 上限((1-聚氯乙烯)*N 行(內維克));
goodVals = (loRank < 排名(內維克) <= hiRank);
好瓦爾斯`*內維克/Sum(goodVals);
對於第 3 項,我正在尋找一個函數,該函數可以查找字串清單中每個項目中給定字串的所有出現情況。 如果給定的字串是“a”且字串列表
{「跟骨」,「狐狸」,「寶貝」}
傳回的值是
{[2, 5, 9, 13, 15, 17],.,[2]}
措辭正確的範例將有助於更準確地定義函數。 我的循環解決方案:
listContains = Function({listIn,valueString},{i,outList,nextMat,start},
outList = Repeat({.},N Items(listIn));
For(i=1,i<=N Items(listIn),i++,
nextMat = [];
start = 1;
While(start = Contains(listIn[i],valueString,start),
nextMat = nextMat |/ start;
start+=Length(valueString);
);
If(N Row(nextMat) > 0,outList[i] = nextMat,outList[i]=.);
);
outList;
);
處理挑戰 1 中從字典中隨機選擇的 100 萬個單字的清單需要 2 到 3 秒的時間。
我的動力應用函數是複製我在其他程式語言中使用的功能,在其中我可以將函數應用(或映射)到聚合資料結構(通常是字串或矩陣列表)。 我希望能夠使用類似的東西:
長度(字串列表)
取得清單中每個項目的長度,而不是使用循環或列公式。
發布挑戰後,我意識到有些細微之處我沒有考慮到,例如該函數可以應用於輸入清單中的單一項目或整個輸入清單的情況。 此外,我沒有提及是否可以將不同的函數參數套用到每個列表元素。
考慮到這一點,並與挑戰 5 條目中的評論保持一致,實施應用函數我提供了四個參數:
列表輸入– 一個或多個數字、字串、向量或字串清單的清單。
號– 要套用的函數的參考名稱列表輸入。 該函數可以是內建的或使用者提供的。
參數列表– 參數列表號之後出現的列表輸入或參數列表的列表。 如果提供了列表列表,則它必須具有與以下相同的基數:列表輸入。
旗幟- 1 如果號套用於清單的每個元素,如果套用於整個清單則為 0。
一種簡單但通用的方法是使用表達式和循環建立函數。 在偽代碼中:
If flag == 1 then
If argList is a list of lists then
For each item in listIn/argList, build an expression for fn
Else
For each item in listIn, build an expression for fn using the same items from argList
Else flag == 0
Build one expression for listIn and argList
這種方法的程式碼可以在applyFunction(循環).JSL 。 @大衛_伯納姆提供了一種遞歸方法Challenge_5_burnham.JSL 。 雖然很優雅(誰不喜歡遞歸?),但如果遞歸太深,它就會遇到問題。
試著使應用函數無循環函數被證明是一個相當大的挑戰。 主要問題是不知道裡面的物品數量參數列表先驗(或更具挑戰性的是,處理數字變化的情況)。起初,我希望能夠透過巧妙地使用表達式求值來實現這一目標。 例如,如果函數只需要一個參數,則以下內容將起作用:
applyFunctionSimple = Function({listIn,fn,argList},{i,fnExpr,outList},
i = 1;
outList = {};
outList[1::N Items(listIn)] = Substitute(
Expr(func(in,arg)),
Expr(func),Parse(fn),
Expr(in), Expr(listIn[i++]),
Expr(arg), argList[1]
);
Eval List(outList)
);
的魔力代替首先產生一個長度列表N 項(列表輸入)列表中的每個元素都是表達式號(列表[i++],精氨酸1 ) , 在哪裡號和精氨酸1在函數呼叫中給出列表[i++]是字面意思。 什麼時候評估清單應用於外列表,然而,每個我給出一個單獨的順序值,並對列表項進行評估,產生所需的結果。 我從以下網站學到了這種使用表達式的方法@約瑟夫_摩根誰,連同@drewfoglia / @EvanMcCorkle已經提供了涵蓋該主題的優秀 Discovery 教程。 教程可以找到這裡和這裡。
不幸的是,我無法弄清楚如何完全使用這種方法,並且不得不依賴一種我試圖避免的技術,因為它效率低下且不優雅,透過字串操作建立通用函數,然後使用表達式求值來獲取輸出。 我的程式碼在applyFunction(無循環).JSL 。 雖然這段程式碼保留了大部分的風格應用函數簡單,正規表示式用於從表達式中去除大括號參數列表。 幸運的是, @Craige_Hales提供了一個純粹基於表達式的解決方案克雷格5.JSL 。 由於它是在後來的挑戰 5 澄清之前發送給我的,因此它適用號到每個元素列表輸入僅有的。 此外,每個函數呼叫都使用相同的參數集。 該解決方案和我的解決方案都存在相同的問題,即比我們基於循環的解決方案慢(2-5 倍之間)。
希望這一切都有道理。 如果沒有,或者您有其他見解,請在下面發表您的評論。

函數來運行函數? 如何? 為什麼?
自動化和腳本編寫