List 筛选包含字符串模式的列表

List 筛选包含字符串模式的列表,list,filter,erlang,List,Filter,Erlang,我需要过滤列表中包含字符串Status=ACTIVE的元素,并将其另存为新列表 稍后,我还需要用Status=STOPPED和System=Windows筛选相同的列表 名单: 通缉结果: ["Process=1,System=Linux,PID=240,Program=DRMX,Status=ACTIVE", "Process=1,System=Windows,PID=240,Program=DRMX,Status=ACTIVE", "Process=1,System=Linu

我需要过滤列表中包含字符串Status=ACTIVE的元素,并将其另存为新列表

稍后,我还需要用Status=STOPPED和System=Windows筛选相同的列表

名单:

通缉结果:

["Process=1,System=Linux,PID=240,Program=DRMX,Status=ACTIVE",
    "Process=1,System=Windows,PID=240,Program=DRMX,Status=ACTIVE",
    "Process=1,System=Linux,PID=242,Program=DRMX,Status=ACTIVE",
    "Process=1,System=Windows,PID=242,Program=DRMX,Status=ACTIVE",
    "Process=1,System=Linux,PID=246,Program=DRMX,Status=ACTIVE",
    "Process=1,System=Linux,PID=246,Program=DRMX,Status=ACTIVE"].
以及:

我找到了可能的解决方案,用re:run/2和list:filter/2对其进行过滤。有没有更简单更快的方法

Filter=fun(Acc)->
    nomatch =/= re:run(Acc,"Status=ACTIVE") end.
Result=lists:filter(Filter,Programs).
比尔


达米安

第一个可以通过

lists:filter(
    fun (A) ->
        lists:member("Status=ACTIVE", string:tokens(A,","))
    end, Programs).
而第二个更为复杂,因为它需要验证两个条件:

lists:filter(
    fun(A) ->
        Tokens = string:tokens(A, ","),
        lists:member("Status=STOPPED", Tokens)
        andalso lists:member("System=Windows", Tokens)
    end, Programs).

我不确定它是否更快,但它至少更可读。

< P>我强烈地考虑将这样的列表解析成记录的列表来对数据结构进行形式化。记录的过滤变得非常优雅:

-record(program,{process,
                 system,
                 pid,
                 program,
                 status}).

% Parse list of strings to list of programs
ParsedPrograms=parseProgram(Programs),
[Valid || Valid = #program{status="STOPPED", system="Windows"} <- ParsedPrograms].

您还可以使用string:str/2或string:find/2,因为str已过时

ListA = [X || X <- Programs, string:str(X, "ACTIVE") > 0],
ListB = [X || X <- Programs, string:str(X, "STOPPED") > 0 and string:str(X, "Windows") > 0].

ListA = [X || X <- Programs, string:find(X, "ACTIVE") /= undefined],
ListB = [X || X <- Programs, string:find(X, "STOPPED") /= undefined and string:find(X, "Windows") /= undefined]
虽然这是完全正确的,但我会写一些关于Erlang最佳实践的文章。一个非常好的实践是尽快将数据从Erlang世界之外转换为适当的Erlang结构。当一个项目变得越来越复杂,需要适当的操作、调试、故障排除等时,它将在长期的项目发展和维护中得到回报。因此,您通常会尽可能多地将文本数据解析为记录、原子、整数、数字等。它允许两件事。首先,您要尽快验证传入的数据,以防止错误在系统内部的边界上传播。这样就可以使用快速模具方法。其次,您可以编写许多帮助器函数,这使得进一步的开发更加容易。差不多

-module(programs).

-record(program, {
          process,
          system,
          pid,
          program,
          status
         }).

%% API

-export([parse_programs/1, active/1, stopped/1, linux/1, windows/1]).

parse_programs(L) ->
    [parse_program(X) || X <- L].

active(P) -> P#program.status =:= active.

stopped(P) -> P#program.status =:= stopped.

linux(P) -> P#program.system =:= 'Linux'.

windows(P) -> P#program.system =:= 'Windows'.

%% Internal functions

parse_program(Str) ->
    parse_program(string:tokens(Str, ","), #program{}).

parse_program([], P) -> P;
parse_program(["Process=" ++ Str | T], P) ->
    parse_program(T, P#program{process = list_to_integer(Str)});
parse_program(["System=" ++ Str | T], P) ->
    parse_program(T, P#program{system = parse_system(Str)});
parse_program(["PID=" ++ Str | T], P) ->
    parse_program(T, P#program{pid = list_to_integer(Str)});
parse_program(["Program=" ++ Str | T], P) ->
    parse_program(T, P#program{program = Str});
parse_program(["Status=" ++ Str | T], P) ->
    parse_program(T, P#program{status = parse_status(Str)});
parse_program([H | _], _) ->
    error(badarg, [H]).

parse_system("Linux") -> 'Linux';
parse_system("Windows") -> 'Windows';
parse_system(Str) -> error(badarg, [Str]).

parse_status("ACTIVE") -> active;
parse_status("STOPPED") -> stopped;
parse_status(Str) -> error(badarg, [Str]).
作为一个副作用,您的程序将消耗更少的内存,因为数字和原子消耗的内存都比字符串少得多。任何进一步的处理都会快得多,因为所有原子的比较就像数字比较一样,更少的内存意味着CPU缓存中有更多的数据,CPU缓存命中比主内存访问快两个数量级

在这种情况下

7> erts_debug:size(Programs).                                         
1062
8> erts_debug:size(Ps).      
153
这意味着您可以在CPU缓存中保留几乎七倍多的数据。当您在Erlang分发中的进程或节点之间发送消息时,速度将提高七倍。。。如果您将list_to_binary/1用作程序名,那么它甚至会相差十倍

parse_program(["Program=" ++ Str | T], P) ->
    parse_program(T, P#program{program = list_to_binary(Str)});
然后


因此,从8.3KB降到864B。

而且也比和好。虽然有这么短的名单,但还是有一点点。谢谢。这个解决方案最适合我的程序。
1> c(programs).
{ok,programs}
2> rr("programs.erl").
[program]
3> Programs=
3>     ["Process=1,System=Linux,PID=240,Program=DRMX,Status=ACTIVE",
3>     "Process=1,System=Linux,PID=240,Program=DRMX,Status=STOPPED",
3>     "Process=1,System=Windows,PID=240,Program=DRMX,Status=ACTIVE",
3>     "Process=1,System=Linux,PID=242,Program=DRMX,Status=ACTIVE",
3>     "Process=1,System=Windows,PID=242,Program=DRMX,Status=STOPPED",
3>     "Process=1,System=Windows,PID=242,Program=DRMX,Status=ACTIVE",
3>     "Process=1,System=Linux,PID=246,Program=DRMX,Status=ACTIVE",
3>     "Process=1,System=Linux,PID=246,Program=DRMX,Status=STOPPED",
3>     "Process=1,System=Linux,PID=246,Program=DRMX,Status=ACTIVE"].
["Process=1,System=Linux,PID=240,Program=DRMX,Status=ACTIVE",
 "Process=1,System=Linux,PID=240,Program=DRMX,Status=STOPPED",
 "Process=1,System=Windows,PID=240,Program=DRMX,Status=ACTIVE",
 "Process=1,System=Linux,PID=242,Program=DRMX,Status=ACTIVE",
 "Process=1,System=Windows,PID=242,Program=DRMX,Status=STOPPED",
 "Process=1,System=Windows,PID=242,Program=DRMX,Status=ACTIVE",
 "Process=1,System=Linux,PID=246,Program=DRMX,Status=ACTIVE",
 "Process=1,System=Linux,PID=246,Program=DRMX,Status=STOPPED",
 "Process=1,System=Linux,PID=246,Program=DRMX,Status=ACTIVE"]
4> Ps = programs:parse_programs(Programs).
[#program{process = 1,system = 'Linux',pid = 240,
          program = "DRMX",status = active},
 #program{process = 1,system = 'Linux',pid = 240,
          program = "DRMX",status = stopped},
 #program{process = 1,system = 'Windows',pid = 240,
          program = "DRMX",status = active},
 #program{process = 1,system = 'Linux',pid = 242,
          program = "DRMX",status = active},
 #program{process = 1,system = 'Windows',pid = 242,
          program = "DRMX",status = stopped},
 #program{process = 1,system = 'Windows',pid = 242, 
          program = "DRMX",status = active},
 #program{process = 1,system = 'Linux',pid = 246,
          program = "DRMX",status = active},
 #program{process = 1,system = 'Linux',pid = 246,
          program = "DRMX",status = stopped},
 #program{process = 1,system = 'Linux',pid = 246,
          program = "DRMX",status = active}]
5> lists:filter(fun programs:active/1, Ps).
[#program{process = 1,system = 'Linux',pid = 240,
          program = "DRMX",status = active},
 #program{process = 1,system = 'Windows',pid = 240,
          program = "DRMX",status = active},
 #program{process = 1,system = 'Linux',pid = 242,
          program = "DRMX",status = active},
 #program{process = 1,system = 'Windows',pid = 242,
          program = "DRMX",status = active},
 #program{process = 1,system = 'Linux',pid = 246,
          program = "DRMX",status = active},
 #program{process = 1,system = 'Linux',pid = 246,
          program = "DRMX",status = active}]
6> lists:filter(fun(P) -> programs:stopped(P) andalso programs:windows(P) end, Ps).
[#program{process = 1,system = 'Windows',pid = 242,
          program = "DRMX",status = stopped}]
7> erts_debug:size(Programs).                                         
1062
8> erts_debug:size(Ps).      
153
parse_program(["Program=" ++ Str | T], P) ->
    parse_program(T, P#program{program = list_to_binary(Str)});
9> c(programs).
{ok,programs}
10> f(Ps).
ok
11> Ps = programs:parse_programs(Programs).
[{program,1,'Linux',240,<<"DRMX">>,active},
 {program,1,'Linux',240,<<"DRMX">>,stopped},
 {program,1,'Windows',240,<<"DRMX">>,active},
 {program,1,'Linux',242,<<"DRMX">>,active},
 {program,1,'Windows',242,<<"DRMX">>,stopped},
 {program,1,'Windows',242,<<"DRMX">>,active},
 {program,1,'Linux',246,<<"DRMX">>,active},
 {program,1,'Linux',246,<<"DRMX">>,stopped},
 {program,1,'Linux',246,<<"DRMX">>,active}]
12> erts_debug:size(Ps).
108