2014-12-03 47 views
1

的名單上有兩個列表:執行清單上的功能和列表(二郎)

Category_list = [a, b, c, d] 
Id_list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]] 

對於Category_list每個元素在ID_LIST第一名單我想執行一個函數的每個元素。想象一下,我有這樣的功能:

Check_id(Category, ID) 

因此我需要將運行check_id這樣的功能(但很多在現實中更多的ID):

Check_id(a, 1), Check_id(a, 2), Check_id(a, 3), Check_id(a, 4), 
Check_id(b, 5), Check_id(b, 6), Check_id(b, 7), Check_id(b, 8), 
Check_id(c, 9), Check_id(c, 10), Check_id(c, 11), Check_id(c, 12), 
Check_id(d, 13), Check_id(d, 14), Check_id(d, 15), Check_id(d, 16). 

在Category_list和元素的量ID_list中元素(列表)的數量將始終相同。我嘗試過使用列表解析以及「列表:foreach」一段時間無濟於事。

回答

1
check_id(C, Id) -> 
    {C, Id}. 

main()-> 
    Category_list = [a, b, c, d], 
    Id_list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]], 

    Zip = lists:zip(Category_list, Id_list), 
    Res = lists:map(fun({C, Ids}) -> [check_id(C, Id) || Id <- Ids] end, Zip), 
    lists:flatten(Res). 

你可以試試這個方法,輸出爲:

[{a,1}, 
{a,2}, 
{a,3}, 
{a,4}, 
{b,5}, 
{b,6}, 
{b,7}, 
{b,8}, 
{c,9}, 
{c,10}, 
{c,11}, 
{c,12}, 
{d,13}, 
{d,14}, 
{d,15}, 
{d,16}] 
1

這裏是沒有索引爲O(n)解決方案

lists:foldl(
    fun (Category, [Ids | Id_listTail]) -> 
     lists:foreach(
      fun (Id) -> 
       Check_id(Category, Id) 
      end, Ids), 
     Id_listTail 
    end, Id_list, Category_list), 

這個列表理解應該爲你工作,以及:

%% note it's O(n^2) solution. Don't use it if Category list is much longer than in example: 
[Check_id(lists:nth(N,Category_list), Id) || 
    N <-lists:seq(1,length(Category_list)), 
    Id <- lists:nth(N,Id_list)]. 

而且順便說一句很常見的做法是所謂的「變數」使用名稱PascalCase

Check_id => CheckId 
Category_list => CategoryList 
Id_list => IdList 
+0

你可以通過命名匿名函數和移動內一出來的foreach提高可讀性。好的Erlang代碼最多嵌套兩次。有一次,因爲你在函數內寫入,第二次在接收語句中寫入:)這可能是極端的,但我通常太愚蠢,無法理解更多的嵌套代碼。使用'foldl'非常好,因爲你沒有創建輔助列表。 – tkowal 2014-12-03 14:37:08

+0

嵌套foldl和foreach的可讀性問題來自於我相信的參數序列,這就是爲什麼我爲我們前一段時間討論的函數編寫了這個函數 - 以更自然的方式編寫它並提高可讀性;)我非常喜歡使用閉包。它有助於保持模塊更簡單。 – 2014-12-03 14:46:14

2

我同意,你應該使用PascalCase,這是大寫首字母的駱駝案件。不過,我不會爲添加人爲索引而煩惱。

-module(category). 

-compile([export_all]). 

run() -> 
    Category_list = [a, b, c, d], 
    Id_list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]], 
    Zipped = lists:zip(Category_list, Id_list), 
    [check_categories(Category, List) || {Category, List} <- Zipped]. 

check_categories(Category, List) -> 
    [check_category(Category, Element) || Element <- List]. 

check_category(Category, Element) -> 
    io:format("~p ~p~n", [Category, Element]). 

lists:zip/2需要兩個列表並將它們合併成元組的列表:

[{a,[1,2,3,4]},{b,[5,6,7,8]},{c,"\t\n\v\f"},{d,[13,14,15,16]}] 

然後,您可以通過與{範疇,ListOfElementsWithThisCategory}元組快速掃描。

0

列表理解需要一個函數,一個類別列表和一個id列表,並執行所有的檢查。它不會對列表和子列表大小產生任何限制(除非是合理的:o)。我添加了一個列表:flatten/1來顯示結果,但如果您不需要收集結果,則它可能毫無用處。

1> Check_id = fun(Cat,Id) -> {Cat,Id} end. 
#Fun<erl_eval.12.90072148> 
2> CatList = [a,b,c]. 
[a,b,c] 
3> IdList = [[1,2,3],[4,5,6]]. 
[[1,2,3],[4,5,6]] 
4> lists:flatten([[Check_id(Cat,Id) || Cat <- CatList, Id <- SubIdList] || SubIdList <- IdList]). 
[{a,1}, 
{a,2}, 
{a,3}, 
{b,1}, 
{b,2}, 
{b,3}, 
{c,1}, 
{c,2}, 
{c,3}, 
{a,4}, 
{a,5}, 
{a,6}, 
{b,4}, 
{b,5}, 
{b,6}, 
{c,4}, 
{c,5}, 
{c,6}] 
5>