假设我有一个看起来像这样的矩阵:
{{foobar, 77},{faabar, 81},{foobur, 22},{faabaa, 8},
{faabian, 88},{foobar, 27}, {fiijii, 52}}
和这样的列表:
{foo, faa}
现在我想基于列表中字符串的部分匹配来添加矩阵中每一行的数字,以便我最终得到:
{{foo, 126},{faa, 177}}
我假设我需要映射一个Select命令,但我不太清楚如何做到并只匹配部分字符串。有谁能够帮我?现在我的真实矩阵大约有150万行,所以不太慢的东西会增加价值。
答案 0 :(得分:3)
这是一个起点:
data={{"foobar",77},{"faabar",81},{"foobur",22},{"faabaa",8},{"faabian",88},{"foobar",27},{"fiijii",52}};
{str,vals}=Transpose[data];
vals=Developer`ToPackedArray[vals];
findValPos[str_List,strPat_String]:=
Flatten[Developer`ToPackedArray[
Position[StringPosition[str,strPat],Except[{}],{1},Heads->False]]]
Total[vals[[findValPos[str,"faa"]]]]
答案 1 :(得分:2)
这是另一种方法。它速度相当快,也很简洁。
data =
{{"foobar", 77},
{"faabar", 81},
{"foobur", 22},
{"faabaa", 8},
{"faabian", 88},
{"foobar", 27},
{"fiijii", 52}};
match = {"foo", "faa"};
f = {#2, Tr @ Pick[#[[All, 2]], StringMatchQ[#[[All, 1]], #2 <> "*"]]} &;
f[data, #]& /@ match
{{"foo", 126}, {"faa", 177}}
您可以使用ruebenko的预处理来提高速度 这大约是他在我的系统上的方法的两倍:
{str, vals} = Transpose[data];
vals = Developer`ToPackedArray[vals];
f2 = {#, Tr @ Pick[vals, StringMatchQ[str, "*" <> # <> "*"]]} &;
f2 /@ match
请注意,在此版本中,我测试不在开头的子字符串,以匹配ruebenko的输出。如果你只想在字符串的开头匹配,这是我在第一个函数中假设的那样,它会更快。
答案 2 :(得分:1)
制作数据
mat = {{"foobar", 77},
{"faabar", 81},
{"foobur", 22},
{"faabaa", 8},
{"faabian", 88},
{"foobar", 27},
{"fiijii", 52}};
lst = {"foo", "faa"};
现在选择
r1 = Select[mat, StringMatchQ[lst[[1]], StringTake[#[[1]], 3]] &];
r2 = Select[mat, StringMatchQ[lst[[2]], StringTake[#[[1]], 3]] &];
{{lst[[1]], Total@r1[[All, 2]]}, {lst[[2]], Total@r2[[All, 2]]}}
给出
{{"foo", 126}, {"faa", 177}}
如果可以的话,我会尽量让它变得更具功能性......
修改(1)强>
以下内容更为一般。 (使用与上述相同的数据):
foo[mat_, lst_] := Select[mat, StringMatchQ[lst, StringTake[#[[1]], 3]] &]
r = Map[foo[mat, #] &, lst];
MapThread[ {#1, Total[#2[[All, 2]]]} &, {lst, r}]
给出
{{"foo", 126}, {"faa", 177}}
所以现在,如果将lst更改为3项而不是2项,则上述相同代码将起作用:
lst = {"foo", "faa", "fii"};
答案 3 :(得分:1)
怎么样:
list = {{"foobar", 77}, {"faabar", 81}, {"foobur", 22}, {"faabaa",
8}, {"faabian", 88}, {"foobar", 27}, {"fiijii", 52}};
t = StringTake[#[[1]], 3] &;
{t[#[[1]]], Total[#[[All, 2]]]} & /@ SplitBy[SortBy[list, t], t]
{{"faa", 177}, {"fii", 52}, {"foo", 126}}
我确信我已经阅读了一篇文章,也许在这里,其中有人描述了一个有效地结合排序和拆分的功能,但我记不住了。如果他们知道,也许其他人可以添加评论。
修改强>
确定必须是就寝时间 - 我怎么能忘记Gatherby
{t[#[[1]]], Total[#[[All, 2]]]} & /@ GatherBy[list, t]
{{"foo", 126}, {"faa", 177}, {"fii", 52}}
请注意,对于140万对的虚拟列表,这需要几秒钟,因此不是一个超快的方法。