w*w
2 楼
版上搜书荐书的方法需要改进。
长期以来,在本版搜书的成功率极低。
很多本版很多人说好的书,去翻一下,能看得下去的,10本中碰不上一本。还不如随便
去一个小说网站一本一本去试。
其实很多人没有意识到,读小说这件事,是一件口味很重要的事。
很多人觉得,自己喜欢的书,就是水平高的书。其实只不过是适合他们的口味而已。
水平这个事,很难有一个客观的评价。同一本书,水平高还是不高,100个人没有100种
,也有几十种不同看法。所以搜书荐书最重要的是口味而不是水平。
所以如果你根据某人说某书是仙草,粮草的推荐去试,10次有9次要撞板。
但是如果有一个和你的口味相同的人推荐,成功率却会大大提高。
以我的经验,搜书成功率最高的办法,是如果你很喜欢某一本书,就去试试同一作者的
其他书。这个成功率能达到90%。
第二种办法,就是如果你很喜欢的一本书,另一个人也很喜欢。就去试试这个人推荐的
书。这个成功率能达到30%-40%。
所以我的建议是,以后推荐书的,列出自己读过的最喜欢的几本书,以及现在正在跟的
书单。如果大家都能这么做,大家都能受益。
长期以来,在本版搜书的成功率极低。
很多本版很多人说好的书,去翻一下,能看得下去的,10本中碰不上一本。还不如随便
去一个小说网站一本一本去试。
其实很多人没有意识到,读小说这件事,是一件口味很重要的事。
很多人觉得,自己喜欢的书,就是水平高的书。其实只不过是适合他们的口味而已。
水平这个事,很难有一个客观的评价。同一本书,水平高还是不高,100个人没有100种
,也有几十种不同看法。所以搜书荐书最重要的是口味而不是水平。
所以如果你根据某人说某书是仙草,粮草的推荐去试,10次有9次要撞板。
但是如果有一个和你的口味相同的人推荐,成功率却会大大提高。
以我的经验,搜书成功率最高的办法,是如果你很喜欢某一本书,就去试试同一作者的
其他书。这个成功率能达到90%。
第二种办法,就是如果你很喜欢的一本书,另一个人也很喜欢。就去试试这个人推荐的
书。这个成功率能达到30%-40%。
所以我的建议是,以后推荐书的,列出自己读过的最喜欢的几本书,以及现在正在跟的
书单。如果大家都能这么做,大家都能受益。
n*p
3 楼
给一个json string。找出所有对应的key不重复的value。
比如输入以下string,找出所有“title"的value
{
"glossary":{
"title":"example",
"GlossDiv":{
"title":"S",
"GlossList":{
"GlossEntry":{
"ID":"SGML",
"SortAs":"SGML",
"title":"S",
"Acronym":"SGML",
"Abbrev":"ISO 8879:1986",
"GlossDef":{ "title": "S"},
"GlossSee":[{"title": "e.g."}, {"another": "etc"}]
}
}
}
}
}
输出要是:含"example","S", ”e.g." 三个值的collection。
注意:这个json string只有一行, 我format了只是方便大家看。
希望各位牛人给出你认为最好的方案。我明天会post我自己的。
比如输入以下string,找出所有“title"的value
{
"glossary":{
"title":"example",
"GlossDiv":{
"title":"S",
"GlossList":{
"GlossEntry":{
"ID":"SGML",
"SortAs":"SGML",
"title":"S",
"Acronym":"SGML",
"Abbrev":"ISO 8879:1986",
"GlossDef":{ "title": "S"},
"GlossSee":[{"title": "e.g."}, {"another": "etc"}]
}
}
}
}
}
输出要是:含"example","S", ”e.g." 三个值的collection。
注意:这个json string只有一行, 我format了只是方便大家看。
希望各位牛人给出你认为最好的方案。我明天会post我自己的。
g*t
5 楼
优书网
【在 w***w 的大作中提到】
: 版上搜书荐书的方法需要改进。
: 长期以来,在本版搜书的成功率极低。
: 很多本版很多人说好的书,去翻一下,能看得下去的,10本中碰不上一本。还不如随便
: 去一个小说网站一本一本去试。
: 其实很多人没有意识到,读小说这件事,是一件口味很重要的事。
: 很多人觉得,自己喜欢的书,就是水平高的书。其实只不过是适合他们的口味而已。
: 水平这个事,很难有一个客观的评价。同一本书,水平高还是不高,100个人没有100种
: ,也有几十种不同看法。所以搜书荐书最重要的是口味而不是水平。
: 所以如果你根据某人说某书是仙草,粮草的推荐去试,10次有9次要撞板。
: 但是如果有一个和你的口味相同的人推荐,成功率却会大大提高。
【在 w***w 的大作中提到】
: 版上搜书荐书的方法需要改进。
: 长期以来,在本版搜书的成功率极低。
: 很多本版很多人说好的书,去翻一下,能看得下去的,10本中碰不上一本。还不如随便
: 去一个小说网站一本一本去试。
: 其实很多人没有意识到,读小说这件事,是一件口味很重要的事。
: 很多人觉得,自己喜欢的书,就是水平高的书。其实只不过是适合他们的口味而已。
: 水平这个事,很难有一个客观的评价。同一本书,水平高还是不高,100个人没有100种
: ,也有几十种不同看法。所以搜书荐书最重要的是口味而不是水平。
: 所以如果你根据某人说某书是仙草,粮草的推荐去试,10次有9次要撞板。
: 但是如果有一个和你的口味相同的人推荐,成功率却会大大提高。
a*e
6 楼
题目不是很严谨啊,如果 "title" 的值是个表,里面还有 "title" 怎么办?
s*n
7 楼
是不是garmin??
a*e
10 楼
我先来一个 FP 方案,是用 Javascript 写的,可以用 node 运行。
https://pastebin.com/NbXkYEjC
定义都是一行,多数都是 boilerplate,或者说它们是通用函数,与题目无关。
与题目相关的逻辑只在于两个定义,addKey 和 collect。
不是很好懂的地方是 traverse 函数,也是这里唯一用到递归的函数。这种方法统称叫
做 recursion scheme,有兴趣的可以 google,也欢迎私信探讨。
https://pastebin.com/NbXkYEjC
定义都是一行,多数都是 boilerplate,或者说它们是通用函数,与题目无关。
与题目相关的逻辑只在于两个定义,addKey 和 collect。
不是很好懂的地方是 traverse 函数,也是这里唯一用到递归的函数。这种方法统称叫
做 recursion scheme,有兴趣的可以 google,也欢迎私信探讨。
n*p
12 楼
谢谢!
你用的input是之前的,我后来改动了一下,json里面有array。
能测试一下新的input吗?
【在 a*****e 的大作中提到】
: 我先来一个 FP 方案,是用 Javascript 写的,可以用 node 运行。
: https://pastebin.com/NbXkYEjC
: 定义都是一行,多数都是 boilerplate,或者说它们是通用函数,与题目无关。
: 与题目相关的逻辑只在于两个定义,addKey 和 collect。
: 不是很好懂的地方是 traverse 函数,也是这里唯一用到递归的函数。这种方法统称叫
: 做 recursion scheme,有兴趣的可以 google,也欢迎私信探讨。
你用的input是之前的,我后来改动了一下,json里面有array。
能测试一下新的input吗?
【在 a*****e 的大作中提到】
: 我先来一个 FP 方案,是用 Javascript 写的,可以用 node 运行。
: https://pastebin.com/NbXkYEjC
: 定义都是一行,多数都是 boilerplate,或者说它们是通用函数,与题目无关。
: 与题目相关的逻辑只在于两个定义,addKey 和 collect。
: 不是很好懂的地方是 traverse 函数,也是这里唯一用到递归的函数。这种方法统称叫
: 做 recursion scheme,有兴趣的可以 google,也欢迎私信探讨。
h*6
13 楼
楼主,你写了几年代码不会连一点比较拿得出手的都没有吧。
n*p
15 楼
好,那我先把你的solution存底:
const id = x => x
const keys = o => Object.keys(o)
const values = o => keys(o).map(x=>o[x])
const assign = (...o) => Object.assign({}, ...o)
const map = f => xs => xs.map(x => f(x));
const omap = f => o => {o = assign(o); map(x => o[x] = f(x,o[x]))(keys(o));
return o}
const triple = (f, g, h) => o => Array.isArray(o) ? f(o) : typeof(o) == '
object' ? g(o) : h(o)
const fmap = f => triple(map(f), omap((k,v)=>f(v)), id)
const traverse = h => x => h(fmap(traverse(h)))(x)
const concat = a => a.reduce((x,y)=>x.concat(y), [])
const addKey = k => x => triple(concat, o => concat(values(o)).concat(x[k] ?
[x[k]] : []), x => [])
const comp = (f, g) => x => f(x)(g(x))
const collect = k => traverse(h => comp(addKey(k),h))
const unique = x => [...new Set(x)]
const solve = k => x => unique(collect(k)(JSON.parse(x)))
x = '{"glossary":{"title":"example","GlossDiv":{"title":"S","GlossList":{"
GlossEntry":{"ID":"SGML","SortAs":"SGML","title":"S","Acronym":"SGML","
Abbrev":"ISO 8879:1986","GlossDef":{"title":"e.g."},"GlossSee":"markup"}}}}}'
console.log(solve('title')(x))
【在 a*****e 的大作中提到】
: 新 input 也没问题
const id = x => x
const keys = o => Object.keys(o)
const values = o => keys(o).map(x=>o[x])
const assign = (...o) => Object.assign({}, ...o)
const map = f => xs => xs.map(x => f(x));
const omap = f => o => {o = assign(o); map(x => o[x] = f(x,o[x]))(keys(o));
return o}
const triple = (f, g, h) => o => Array.isArray(o) ? f(o) : typeof(o) == '
object' ? g(o) : h(o)
const fmap = f => triple(map(f), omap((k,v)=>f(v)), id)
const traverse = h => x => h(fmap(traverse(h)))(x)
const concat = a => a.reduce((x,y)=>x.concat(y), [])
const addKey = k => x => triple(concat, o => concat(values(o)).concat(x[k] ?
[x[k]] : []), x => [])
const comp = (f, g) => x => f(x)(g(x))
const collect = k => traverse(h => comp(addKey(k),h))
const unique = x => [...new Set(x)]
const solve = k => x => unique(collect(k)(JSON.parse(x)))
x = '{"glossary":{"title":"example","GlossDiv":{"title":"S","GlossList":{"
GlossEntry":{"ID":"SGML","SortAs":"SGML","title":"S","Acronym":"SGML","
Abbrev":"ISO 8879:1986","GlossDef":{"title":"e.g."},"GlossSee":"markup"}}}}}'
console.log(solve('title')(x))
【在 a*****e 的大作中提到】
: 新 input 也没问题
T*x
16 楼
这个代码看着很高大上啊。
:我先来一个 FP 方案,是用 Javascript 写的,可以用 node 运行。
:
:我先来一个 FP 方案,是用 Javascript 写的,可以用 node 运行。
:
n*p
17 楼
here you go, in clojure:
(def m (clojure.data.json/read-str
"{ "glossary":{ "title":"example", "GlossDiv":{ "title":"S", "GlossList":{ "
title":{ "ID":"SGML", "SortAs":"SGML", "title":"S", "Acronym":"SGML", "
Abbrev":"ISO 8879:1986", "GlossDef":{ "title": "S"}, "GlossSee":[{"title": "
e.g."}, {"another": "etc"}] } } } } }"
))
(->> (tree-seq #(or (map? %) (vector? %)) identity m)
(keep #(get % "title"))
(filter #(not (map? %)))
set
)
Test code in REPL:
>lein repl
user=> (use 'clojure.data.json)
user=>
(def m (clojure.data.json/read-str
#_=> "{ "glossary":{ "title":"e, "GlossSee":[{"title": "e.g."}, {"another"
", "Abbrev":"ISO 8879:1986", "GlossDef":{ "title": "S"}
#_=> ))
#'user/m
user=> (->> (tree-seq #(or (map? %) (vector? %)) identity m)
#_=> (keep #(get % "title"))
#_=> (filter #(not (map? %)))
#_=> set
#_=> )
#{"example" "S" "e.g."}
2 vs 0, FP FTW :)
(def m (clojure.data.json/read-str
"{ "glossary":{ "title":"example", "GlossDiv":{ "title":"S", "GlossList":{ "
title":{ "ID":"SGML", "SortAs":"SGML", "title":"S", "Acronym":"SGML", "
Abbrev":"ISO 8879:1986", "GlossDef":{ "title": "S"}, "GlossSee":[{"title": "
e.g."}, {"another": "etc"}] } } } } }"
))
(->> (tree-seq #(or (map? %) (vector? %)) identity m)
(keep #(get % "title"))
(filter #(not (map? %)))
set
)
Test code in REPL:
>lein repl
user=> (use 'clojure.data.json)
user=>
(def m (clojure.data.json/read-str
#_=> "{ "glossary":{ "title":"e, "GlossSee":[{"title": "e.g."}, {"another"
", "Abbrev":"ISO 8879:1986", "GlossDef":{ "title": "S"}
#_=> ))
#'user/m
user=> (->> (tree-seq #(or (map? %) (vector? %)) identity m)
#_=> (keep #(get % "title"))
#_=> (filter #(not (map? %)))
#_=> set
#_=> )
#{"example" "S" "e.g."}
2 vs 0, FP FTW :)
m*o
18 楼
觉得正确的做法是边parse json边accumulate map
;
【在 n***p 的大作中提到】
: 好,那我先把你的solution存底:
: const id = x => x
: const keys = o => Object.keys(o)
: const values = o => keys(o).map(x=>o[x])
: const assign = (...o) => Object.assign({}, ...o)
: const map = f => xs => xs.map(x => f(x));
: const omap = f => o => {o = assign(o); map(x => o[x] = f(x,o[x]))(keys(o));
: return o}
: const triple = (f, g, h) => o => Array.isArray(o) ? f(o) : typeof(o) == '
: object' ? g(o) : h(o)
;
【在 n***p 的大作中提到】
: 好,那我先把你的solution存底:
: const id = x => x
: const keys = o => Object.keys(o)
: const values = o => keys(o).map(x=>o[x])
: const assign = (...o) => Object.assign({}, ...o)
: const map = f => xs => xs.map(x => f(x));
: const omap = f => o => {o = assign(o); map(x => o[x] = f(x,o[x]))(keys(o));
: return o}
: const triple = (f, g, h) => o => Array.isArray(o) ? f(o) : typeof(o) == '
: object' ? g(o) : h(o)
s*y
19 楼
感觉挺简单啊 就是个recursive 一直往下找就好了
d*c
21 楼
FP的特点就是避开那个复杂的包含一切的loop
一边parse一边做事,相比parse一遍,筛选一遍,加工一遍看起来节省一些扫描次数,
但是实际性能差别未必很大,最重要的是思维负担很大。
要在loop中一边扫描一边做事,就需要一直维护状态,例外情况会很复杂,如果要求变
化了会更复杂,而且很难一下子理解全部内容,过段时间自己都看不懂。
FP把动作抽象出来,每个动作都是库函数,不需要自己写,思维负担要小很多,需求变
化也容易调整。真要有性能瓶颈再根据具体情况去优化就是了。
一边parse一边做事,相比parse一遍,筛选一遍,加工一遍看起来节省一些扫描次数,
但是实际性能差别未必很大,最重要的是思维负担很大。
要在loop中一边扫描一边做事,就需要一直维护状态,例外情况会很复杂,如果要求变
化了会更复杂,而且很难一下子理解全部内容,过段时间自己都看不懂。
FP把动作抽象出来,每个动作都是库函数,不需要自己写,思维负担要小很多,需求变
化也容易调整。真要有性能瓶颈再根据具体情况去优化就是了。
d*a
23 楼
这个有意思。下面是pythod版本,程序存为match.py,输入存到input.txt,运行命令
是python match.py < input.txt。
import sys
import re
from sets import Set
pattern = "\"title\":\s*\"([\w\.]*)\""
titles = Set()
for line in sys.stdin:
match = re.search(pattern, line)
if match:
titles.add(match.group(1))
for title in titles:
print title
是python match.py < input.txt。
import sys
import re
from sets import Set
pattern = "\"title\":\s*\"([\w\.]*)\""
titles = Set()
for line in sys.stdin:
match = re.search(pattern, line)
if match:
titles.add(match.group(1))
for title in titles:
print title
a*e
24 楼
一行有多个 title 这个就出错了。Writing your own parser is almost always
unnecessary, and error prone.
【在 d***a 的大作中提到】
: 这个有意思。下面是pythod版本,程序存为match.py,输入存到input.txt,运行命令
: 是python match.py < input.txt。
: import sys
: import re
: from sets import Set
: pattern = "\"title\":\s*\"([\w\.]*)\""
: titles = Set()
: for line in sys.stdin:
: match = re.search(pattern, line)
: if match:
unnecessary, and error prone.
【在 d***a 的大作中提到】
: 这个有意思。下面是pythod版本,程序存为match.py,输入存到input.txt,运行命令
: 是python match.py < input.txt。
: import sys
: import re
: from sets import Set
: pattern = "\"title\":\s*\"([\w\.]*)\""
: titles = Set()
: for line in sys.stdin:
: match = re.search(pattern, line)
: if match:
a*e
25 楼
用 tree-seq 有点 cheat 了。tree-seq 已经可以把 tree 扁平化成列表,接下来得工
作微乎其微啊
"
"
【在 n***p 的大作中提到】
: here you go, in clojure:
: (def m (clojure.data.json/read-str
: "{ "glossary":{ "title":"example", "GlossDiv":{ "title":"S", "GlossList":{ "
: title":{ "ID":"SGML", "SortAs":"SGML", "title":"S", "Acronym":"SGML", "
: Abbrev":"ISO 8879:1986", "GlossDef":{ "title": "S"}, "GlossSee":[{"title": "
: e.g."}, {"another": "etc"}] } } } } }"
: ))
: (->> (tree-seq #(or (map? %) (vector? %)) identity m)
: (keep #(get % "title"))
: (filter #(not (map? %)))
作微乎其微啊
"
"
【在 n***p 的大作中提到】
: here you go, in clojure:
: (def m (clojure.data.json/read-str
: "{ "glossary":{ "title":"example", "GlossDiv":{ "title":"S", "GlossList":{ "
: title":{ "ID":"SGML", "SortAs":"SGML", "title":"S", "Acronym":"SGML", "
: Abbrev":"ISO 8879:1986", "GlossDef":{ "title": "S"}, "GlossSee":[{"title": "
: e.g."}, {"another": "etc"}] } } } } }"
: ))
: (->> (tree-seq #(or (map? %) (vector? %)) identity m)
: (keep #(get % "title"))
: (filter #(not (map? %)))
n*p
27 楼
It's not hard to write tree-seq, 不到10行code
https://cljs.github.io/api/cljs.core/tree-seq
【在 a*****e 的大作中提到】
: 用 tree-seq 有点 cheat 了。tree-seq 已经可以把 tree 扁平化成列表,接下来得工
: 作微乎其微啊
:
: "
: "
https://cljs.github.io/api/cljs.core/tree-seq
【在 a*****e 的大作中提到】
: 用 tree-seq 有点 cheat 了。tree-seq 已经可以把 tree 扁平化成列表,接下来得工
: 作微乎其微啊
:
: "
: "
d*a
29 楼
啊,我看的太快了。:) 下面这个版本可以满足要求。
import sys
import json
from sets import Set
# Define an object hook function to check title
def check_title(dct):
if "title" in dct and type(dct["title"]) == unicode:
titles.add(dct["title"])
return dct
# Load json string with the hook function
titles = Set()
json.load(sys.stdin, object_hook=check_title)
# Print out titles
for title in titles:
print title
【在 n***p 的大作中提到】
: 我有写注意事项,你没看到 :)
n*p
30 楼
好奇集合 titles怎么pass 到check_title function的。
另外这个好像不可以handle title对应的是个Json吧,比如原帖给的sample。
【在 d***a 的大作中提到】
:
: 啊,我看的太快了。:) 下面这个版本可以满足要求。
: import sys
: import json
: from sets import Set
: # Define an object hook function to check title
: def check_title(dct):
: if "title" in dct and type(dct["title"]) == unicode:
: titles.add(dct["title"])
: return dct
另外这个好像不可以handle title对应的是个Json吧,比如原帖给的sample。
【在 d***a 的大作中提到】
:
: 啊,我看的太快了。:) 下面这个版本可以满足要求。
: import sys
: import json
: from sets import Set
: # Define an object hook function to check title
: def check_title(dct):
: if "title" in dct and type(dct["title"]) == unicode:
: titles.add(dct["title"])
: return dct
m*o
35 楼
用了龙太子的fastparse, collect函数是答案。注意把代码中的[back slash]去掉。这
个解法边parse json边收集结果,效
果应该比先parse完json再处理对应的dictionary/map要好一点。
import fastparse.all._
val space = P( CharsWhileIn(" \[back slash]r\[back slash]n").? )
val digits = P( CharsWhileIn("0123456789"))
val exponent = P( CharIn("eE") ~ CharIn("+-").? ~ digits )
val fractional = P( "." ~ digits )
val integral = P( "0" | CharIn('1' to '9') ~ digits.? )
val number = P( CharIn("+-").? ~ integral ~ fractional.? ~ exponent.? ).
map(_ => Set.empty[String])
val `null` = P( "null" ).map(_ => Set.empty[String])
val `false` = P( "false" ).map(_ => Set.empty[String])
val `true` = P( "true" ).map(_ => Set.empty[String])
val hexDigit = P( CharIn('0'to'9', 'a'to'f', 'A'to'F') )
val unicodeEscape = P( "u" ~ hexDigit ~ hexDigit ~ hexDigit ~ hexDigit )
val escape = P( "\[back slash]\[back slash]" ~ (CharIn("\[back
slash]"/\[back slash]\[back slash]bfnrt") | unicodeEscape) )
val strChars = P( CharsWhile(!"\[back slash]"\[back slash]\[back slash]".
contains(_: Char)) )
val string =
P( space ~ "\[back slash]"" ~/ (strChars | escape).rep.! ~ "\[back slash
]"")
val stringValue = string.map(Set(_))
def pair = (string ~/ ":" ~/ (stringValue.map(Left(_)) | expr.map(Right(_)
))) map { case (k, v) =>
if (k == "title") v.fold(identity, identity)
else v.fold(_ => Set.empty[String], identity)
}
def obj =
P( "{" ~/ pair.rep(sep=",".~/) ~ space ~ "}").map(_.reduce(_ union _))
def array =
P( "[" ~/ expr.rep(sep=",".~/) ~ space ~ "]").map(_.reduce(_ union _))
def expr : Parser[Set[String]]= P(
space ~ (obj | array | stringValue.map(_ => Set.empty[String]) | `true`
| `false` | `null` | number) ~ space
)
def collect(json: String): Set[String] =
expr.parse(json) match {
case Success(set, _) => set
case _ => Set.empty
}
【在 n***p 的大作中提到】
: 给一个json string。找出所有对应的key不重复的value。
: 比如输入以下string,找出所有“title"的value
: {
: "glossary":{
: "title":"example",
: "GlossDiv":{
: "title":"S",
: "GlossList":{
: "GlossEntry":{
: "ID":"SGML",
个解法边parse json边收集结果,效
果应该比先parse完json再处理对应的dictionary/map要好一点。
import fastparse.all._
val space = P( CharsWhileIn(" \[back slash]r\[back slash]n").? )
val digits = P( CharsWhileIn("0123456789"))
val exponent = P( CharIn("eE") ~ CharIn("+-").? ~ digits )
val fractional = P( "." ~ digits )
val integral = P( "0" | CharIn('1' to '9') ~ digits.? )
val number = P( CharIn("+-").? ~ integral ~ fractional.? ~ exponent.? ).
map(_ => Set.empty[String])
val `null` = P( "null" ).map(_ => Set.empty[String])
val `false` = P( "false" ).map(_ => Set.empty[String])
val `true` = P( "true" ).map(_ => Set.empty[String])
val hexDigit = P( CharIn('0'to'9', 'a'to'f', 'A'to'F') )
val unicodeEscape = P( "u" ~ hexDigit ~ hexDigit ~ hexDigit ~ hexDigit )
val escape = P( "\[back slash]\[back slash]" ~ (CharIn("\[back
slash]"/\[back slash]\[back slash]bfnrt") | unicodeEscape) )
val strChars = P( CharsWhile(!"\[back slash]"\[back slash]\[back slash]".
contains(_: Char)) )
val string =
P( space ~ "\[back slash]"" ~/ (strChars | escape).rep.! ~ "\[back slash
]"")
val stringValue = string.map(Set(_))
def pair = (string ~/ ":" ~/ (stringValue.map(Left(_)) | expr.map(Right(_)
))) map { case (k, v) =>
if (k == "title") v.fold(identity, identity)
else v.fold(_ => Set.empty[String], identity)
}
def obj =
P( "{" ~/ pair.rep(sep=",".~/) ~ space ~ "}").map(_.reduce(_ union _))
def array =
P( "[" ~/ expr.rep(sep=",".~/) ~ space ~ "]").map(_.reduce(_ union _))
def expr : Parser[Set[String]]= P(
space ~ (obj | array | stringValue.map(_ => Set.empty[String]) | `true`
| `false` | `null` | number) ~ space
)
def collect(json: String): Set[String] =
expr.parse(json) match {
case Success(set, _) => set
case _ => Set.empty
}
【在 n***p 的大作中提到】
: 给一个json string。找出所有对应的key不重复的value。
: 比如输入以下string,找出所有“title"的value
: {
: "glossary":{
: "title":"example",
: "GlossDiv":{
: "title":"S",
: "GlossList":{
: "GlossEntry":{
: "ID":"SGML",
n*p
36 楼
所有答案里有OOP吗?
n*7
37 楼
贴个C#的,test通过
对json处理不熟,我其实感觉用正则表达式抓一下就好了?
---
Code
---
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
namespace Mitbbs
{
public static class Utilities
{
public static IEnumerable FindUniqueValuesFromKey(string
json, string key) =>
ProcessJsonToken(JObject.Parse(json)).Where(x => x.Key == key).
Select(x => x.Value).Distinct();
private static IEnumerable
ProcessJsonToken(JToken jToken)
{
switch (jToken)
{
case JProperty jProperty:
return ProcessJsonProperty(jProperty);
case JArray jArray:
return jArray.Children().Select(ProcessJsonToken).
SelectMany(x => x);
case JObject jObject:
return jObject.Properties().Select(ProcessJsonToken).
SelectMany(x => x);
default:
return new(string, string)[] { };
}
}
private static IEnumerable
ProcessJsonProperty(JProperty jProperty)
{
switch (jProperty.Value.Type)
{
case JTokenType.String:
return new[] {(jProperty.Name, jProperty.Value.ToString(
))};
case JTokenType.Object:
case JTokenType.Property:
case JTokenType.Array:
return jProperty.Value.Children().Select(
ProcessJsonToken).SelectMany(x => x);
default:
return new (string, string)[] { };
}
}
}
}
---
Test
---
using Mitbbs;
using Xunit;
namespace Unittests
{
public class UtilitiesTests
{
private const string Json = @"{
'glossary':{
'title':'example',
'GlossDiv':{
'title':'S',
'GlossList':{
'title':{
'ID':'SGML',
'SortAs':'SGML',
'title':'S',
'Acronym':'SGML',
'Abbrev':'ISO 8879:1986',
'GlossDef':{ 'title': 'S'},
'GlossSee':[{'title': 'e.g.'}, {'another
': 'etc'}]
}
}
}
}
}";
[Fact]
public void FindUniqueValuesFromKey_AsExpected()
{
var expected = new[] { "example", "S", "e.g." };
Assert.Equal(expected, Utilities.FindUniqueValuesFromKey(Json, "
title"));
}
}
}
【在 n***p 的大作中提到】
: 所有答案里有OOP吗?
对json处理不熟,我其实感觉用正则表达式抓一下就好了?
---
Code
---
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
namespace Mitbbs
{
public static class Utilities
{
public static IEnumerable
json, string key) =>
ProcessJsonToken(JObject.Parse(json)).Where(x => x.Key == key).
Select(x => x.Value).Distinct();
private static IEnumerable
ProcessJsonToken(JToken jToken)
{
switch (jToken)
{
case JProperty jProperty:
return ProcessJsonProperty(jProperty);
case JArray jArray:
return jArray.Children().Select(ProcessJsonToken).
SelectMany(x => x);
case JObject jObject:
return jObject.Properties().Select(ProcessJsonToken).
SelectMany(x => x);
default:
return new(string, string)[] { };
}
}
private static IEnumerable
ProcessJsonProperty(JProperty jProperty)
{
switch (jProperty.Value.Type)
{
case JTokenType.String:
return new[] {(jProperty.Name, jProperty.Value.ToString(
))};
case JTokenType.Object:
case JTokenType.Property:
case JTokenType.Array:
return jProperty.Value.Children().Select(
ProcessJsonToken).SelectMany(x => x);
default:
return new (string, string)[] { };
}
}
}
}
---
Test
---
using Mitbbs;
using Xunit;
namespace Unittests
{
public class UtilitiesTests
{
private const string Json = @"{
'glossary':{
'title':'example',
'GlossDiv':{
'title':'S',
'GlossList':{
'title':{
'ID':'SGML',
'SortAs':'SGML',
'title':'S',
'Acronym':'SGML',
'Abbrev':'ISO 8879:1986',
'GlossDef':{ 'title': 'S'},
'GlossSee':[{'title': 'e.g.'}, {'another
': 'etc'}]
}
}
}
}
}";
[Fact]
public void FindUniqueValuesFromKey_AsExpected()
{
var expected = new[] { "example", "S", "e.g." };
Assert.Equal(expected, Utilities.FindUniqueValuesFromKey(Json, "
title"));
}
}
}
【在 n***p 的大作中提到】
: 所有答案里有OOP吗?
n*p
40 楼
给一个json string。找出所有对应的key不重复的value。
比如输入以下string,找出所有“title"的value
{
"glossary":{
"title":"example",
"GlossDiv":{
"title":"S",
"GlossList":{
"title":{
"ID":"SGML",
"SortAs":"SGML",
"title":"S",
"Acronym":"SGML",
"Abbrev":"ISO 8879:1986",
"GlossDef":{ "title": "S"},
"GlossSee":[{"title": "e.g."}, {"another": "etc"}]
}
}
}
}
}
输出要是:含"example","S", ”e.g." 三个值的collection。
注意:这个json string只有一行, 我format了只是方便大家看。
希望各位牛人给出你认为最好的方案。我明天会post我自己的。
比如输入以下string,找出所有“title"的value
{
"glossary":{
"title":"example",
"GlossDiv":{
"title":"S",
"GlossList":{
"title":{
"ID":"SGML",
"SortAs":"SGML",
"title":"S",
"Acronym":"SGML",
"Abbrev":"ISO 8879:1986",
"GlossDef":{ "title": "S"},
"GlossSee":[{"title": "e.g."}, {"another": "etc"}]
}
}
}
}
}
输出要是:含"example","S", ”e.g." 三个值的collection。
注意:这个json string只有一行, 我format了只是方便大家看。
希望各位牛人给出你认为最好的方案。我明天会post我自己的。
a*e
41 楼
题目不是很严谨啊,如果 "title" 的值是个表,里面还有 "title" 怎么办?
a*e
43 楼
我先来一个 FP 方案,是用 Javascript 写的,可以用 node 运行。
https://pastebin.com/NbXkYEjC
定义都是一行,多数都是 boilerplate,或者说它们是通用函数,与题目无关。
与题目相关的逻辑只在于两个定义,addKey 和 collect。
不是很好懂的地方是 traverse 函数,也是这里唯一用到递归的函数。这种方法统称叫
做 recursion scheme,有兴趣的可以 google,也欢迎私信探讨。
https://pastebin.com/NbXkYEjC
定义都是一行,多数都是 boilerplate,或者说它们是通用函数,与题目无关。
与题目相关的逻辑只在于两个定义,addKey 和 collect。
不是很好懂的地方是 traverse 函数,也是这里唯一用到递归的函数。这种方法统称叫
做 recursion scheme,有兴趣的可以 google,也欢迎私信探讨。
n*p
44 楼
谢谢!
你用的input是之前的,我后来改动了一下,json里面有array。
能测试一下新的input吗?
【在 a*****e 的大作中提到】
: 我先来一个 FP 方案,是用 Javascript 写的,可以用 node 运行。
: https://pastebin.com/NbXkYEjC
: 定义都是一行,多数都是 boilerplate,或者说它们是通用函数,与题目无关。
: 与题目相关的逻辑只在于两个定义,addKey 和 collect。
: 不是很好懂的地方是 traverse 函数,也是这里唯一用到递归的函数。这种方法统称叫
: 做 recursion scheme,有兴趣的可以 google,也欢迎私信探讨。
你用的input是之前的,我后来改动了一下,json里面有array。
能测试一下新的input吗?
【在 a*****e 的大作中提到】
: 我先来一个 FP 方案,是用 Javascript 写的,可以用 node 运行。
: https://pastebin.com/NbXkYEjC
: 定义都是一行,多数都是 boilerplate,或者说它们是通用函数,与题目无关。
: 与题目相关的逻辑只在于两个定义,addKey 和 collect。
: 不是很好懂的地方是 traverse 函数,也是这里唯一用到递归的函数。这种方法统称叫
: 做 recursion scheme,有兴趣的可以 google,也欢迎私信探讨。
n*p
46 楼
好,那我先把你的solution存底:
const id = x => x
const keys = o => Object.keys(o)
const values = o => keys(o).map(x=>o[x])
const assign = (...o) => Object.assign({}, ...o)
const map = f => xs => xs.map(x => f(x));
const omap = f => o => {o = assign(o); map(x => o[x] = f(x,o[x]))(keys(o));
return o}
const triple = (f, g, h) => o => Array.isArray(o) ? f(o) : typeof(o) == '
object' ? g(o) : h(o)
const fmap = f => triple(map(f), omap((k,v)=>f(v)), id)
const traverse = h => x => h(fmap(traverse(h)))(x)
const concat = a => a.reduce((x,y)=>x.concat(y), [])
const addKey = k => x => triple(concat, o => concat(values(o)).concat(x[k] ?
[x[k]] : []), x => [])
const comp = (f, g) => x => f(x)(g(x))
const collect = k => traverse(h => comp(addKey(k),h))
const unique = x => [...new Set(x)]
const solve = k => x => unique(collect(k)(JSON.parse(x)))
x = '{"glossary":{"title":"example","GlossDiv":{"title":"S","GlossList":{"
GlossEntry":{"ID":"SGML","SortAs":"SGML","title":"S","Acronym":"SGML","
Abbrev":"ISO 8879:1986","GlossDef":{"title":"e.g."},"GlossSee":"markup"}}}}}'
console.log(solve('title')(x))
【在 a*****e 的大作中提到】
: 新 input 也没问题
const id = x => x
const keys = o => Object.keys(o)
const values = o => keys(o).map(x=>o[x])
const assign = (...o) => Object.assign({}, ...o)
const map = f => xs => xs.map(x => f(x));
const omap = f => o => {o = assign(o); map(x => o[x] = f(x,o[x]))(keys(o));
return o}
const triple = (f, g, h) => o => Array.isArray(o) ? f(o) : typeof(o) == '
object' ? g(o) : h(o)
const fmap = f => triple(map(f), omap((k,v)=>f(v)), id)
const traverse = h => x => h(fmap(traverse(h)))(x)
const concat = a => a.reduce((x,y)=>x.concat(y), [])
const addKey = k => x => triple(concat, o => concat(values(o)).concat(x[k] ?
[x[k]] : []), x => [])
const comp = (f, g) => x => f(x)(g(x))
const collect = k => traverse(h => comp(addKey(k),h))
const unique = x => [...new Set(x)]
const solve = k => x => unique(collect(k)(JSON.parse(x)))
x = '{"glossary":{"title":"example","GlossDiv":{"title":"S","GlossList":{"
GlossEntry":{"ID":"SGML","SortAs":"SGML","title":"S","Acronym":"SGML","
Abbrev":"ISO 8879:1986","GlossDef":{"title":"e.g."},"GlossSee":"markup"}}}}}'
console.log(solve('title')(x))
【在 a*****e 的大作中提到】
: 新 input 也没问题
T*x
47 楼
这个代码看着很高大上啊。
:我先来一个 FP 方案,是用 Javascript 写的,可以用 node 运行。
:
:我先来一个 FP 方案,是用 Javascript 写的,可以用 node 运行。
:
n*p
48 楼
here you go, in clojure:
(->> (tree-seq #(or (map? %) (vector? %)) identity m)
(keep #(get % "title"))
(filter #(not (map? %)))
set
)
Test code in REPL:
>lein repl
user=> (use 'clojure.data.json)
user=>
(def m (clojure.data.json/read-str
#_=> "{ "glossary":{ "title":"e, "GlossSee":[{"title": "e.g."}, {"another"
", "Abbrev":"ISO 8879:1986", "GlossDef":{ "title": "S"}
#_=> ))
#'user/m
user=> (->> (tree-seq #(or (map? %) (vector? %)) identity m)
#_=> (keep #(get % "title"))
#_=> (filter #(not (map? %)))
#_=> set
#_=> )
#{"example" "S" "e.g."}
2 vs 0, FP FTW :)
(->> (tree-seq #(or (map? %) (vector? %)) identity m)
(keep #(get % "title"))
(filter #(not (map? %)))
set
)
Test code in REPL:
>lein repl
user=> (use 'clojure.data.json)
user=>
(def m (clojure.data.json/read-str
#_=> "{ "glossary":{ "title":"e, "GlossSee":[{"title": "e.g."}, {"another"
", "Abbrev":"ISO 8879:1986", "GlossDef":{ "title": "S"}
#_=> ))
#'user/m
user=> (->> (tree-seq #(or (map? %) (vector? %)) identity m)
#_=> (keep #(get % "title"))
#_=> (filter #(not (map? %)))
#_=> set
#_=> )
#{"example" "S" "e.g."}
2 vs 0, FP FTW :)
m*o
49 楼
觉得正确的做法是边parse json边accumulate map
;
【在 n***p 的大作中提到】
: 好,那我先把你的solution存底:
: const id = x => x
: const keys = o => Object.keys(o)
: const values = o => keys(o).map(x=>o[x])
: const assign = (...o) => Object.assign({}, ...o)
: const map = f => xs => xs.map(x => f(x));
: const omap = f => o => {o = assign(o); map(x => o[x] = f(x,o[x]))(keys(o));
: return o}
: const triple = (f, g, h) => o => Array.isArray(o) ? f(o) : typeof(o) == '
: object' ? g(o) : h(o)
;
【在 n***p 的大作中提到】
: 好,那我先把你的solution存底:
: const id = x => x
: const keys = o => Object.keys(o)
: const values = o => keys(o).map(x=>o[x])
: const assign = (...o) => Object.assign({}, ...o)
: const map = f => xs => xs.map(x => f(x));
: const omap = f => o => {o = assign(o); map(x => o[x] = f(x,o[x]))(keys(o));
: return o}
: const triple = (f, g, h) => o => Array.isArray(o) ? f(o) : typeof(o) == '
: object' ? g(o) : h(o)
s*y
50 楼
感觉挺简单啊 就是个recursive 一直往下找就好了
d*c
52 楼
FP的特点就是避开那个复杂的包含一切的loop
一边parse一边做事,相比parse一遍,筛选一遍,加工一遍看起来节省一些扫描次数,
但是实际性能差别未必很大,最重要的是思维负担很大。
要在loop中一边扫描一边做事,就需要一直维护状态,例外情况会很复杂,如果要求变
化了会更复杂,而且很难一下子理解全部内容,过段时间自己都看不懂。
FP把动作抽象出来,每个动作都是库函数,不需要自己写,思维负担要小很多,需求变
化也容易调整。真要有性能瓶颈再根据具体情况去优化就是了。
一边parse一边做事,相比parse一遍,筛选一遍,加工一遍看起来节省一些扫描次数,
但是实际性能差别未必很大,最重要的是思维负担很大。
要在loop中一边扫描一边做事,就需要一直维护状态,例外情况会很复杂,如果要求变
化了会更复杂,而且很难一下子理解全部内容,过段时间自己都看不懂。
FP把动作抽象出来,每个动作都是库函数,不需要自己写,思维负担要小很多,需求变
化也容易调整。真要有性能瓶颈再根据具体情况去优化就是了。
d*a
54 楼
这个有意思。下面是pythod版本,程序存为match.py,输入存到input.txt,运行命令
是python match.py < input.txt。
import sys
import re
from sets import Set
pattern = "\"title\":\s*\"([\w\.]*)\""
titles = Set()
for line in sys.stdin:
match = re.search(pattern, line)
if match:
titles.add(match.group(1))
for title in titles:
print title
是python match.py < input.txt。
import sys
import re
from sets import Set
pattern = "\"title\":\s*\"([\w\.]*)\""
titles = Set()
for line in sys.stdin:
match = re.search(pattern, line)
if match:
titles.add(match.group(1))
for title in titles:
print title
a*e
55 楼
一行有多个 title 这个就出错了。Writing your own parser is almost always
unnecessary, and error prone.
【在 d***a 的大作中提到】
: 这个有意思。下面是pythod版本,程序存为match.py,输入存到input.txt,运行命令
: 是python match.py < input.txt。
: import sys
: import re
: from sets import Set
: pattern = "\"title\":\s*\"([\w\.]*)\""
: titles = Set()
: for line in sys.stdin:
: match = re.search(pattern, line)
: if match:
unnecessary, and error prone.
【在 d***a 的大作中提到】
: 这个有意思。下面是pythod版本,程序存为match.py,输入存到input.txt,运行命令
: 是python match.py < input.txt。
: import sys
: import re
: from sets import Set
: pattern = "\"title\":\s*\"([\w\.]*)\""
: titles = Set()
: for line in sys.stdin:
: match = re.search(pattern, line)
: if match:
n*p
58 楼
It's not hard to write tree-seq, 不到10行code
https://cljs.github.io/api/cljs.core/tree-seq
【在 a*****e 的大作中提到】
: 用 tree-seq 有点 cheat 了。tree-seq 已经可以把 tree 扁平化成列表,接下来得工
: 作微乎其微啊
:
: "
: "
https://cljs.github.io/api/cljs.core/tree-seq
【在 a*****e 的大作中提到】
: 用 tree-seq 有点 cheat 了。tree-seq 已经可以把 tree 扁平化成列表,接下来得工
: 作微乎其微啊
:
: "
: "
d*a
60 楼
啊,我看的太快了。:) 下面这个版本可以满足要求。
import sys
import json
from sets import Set
# Define an object hook function to check title
def check_title(dct):
if "title" in dct and type(dct["title"]) == unicode:
titles.add(dct["title"])
return dct
# Load json string with the hook function
titles = Set()
json.load(sys.stdin, object_hook=check_title)
# Print out titles
for title in titles:
print title
【在 n***p 的大作中提到】
: 我有写注意事项,你没看到 :)
n*p
61 楼
好奇集合 titles怎么pass 到check_title function的。
另外这个好像不可以handle title对应的是个Json吧,比如原帖给的sample。
【在 d***a 的大作中提到】
:
: 啊,我看的太快了。:) 下面这个版本可以满足要求。
: import sys
: import json
: from sets import Set
: # Define an object hook function to check title
: def check_title(dct):
: if "title" in dct and type(dct["title"]) == unicode:
: titles.add(dct["title"])
: return dct
另外这个好像不可以handle title对应的是个Json吧,比如原帖给的sample。
【在 d***a 的大作中提到】
:
: 啊,我看的太快了。:) 下面这个版本可以满足要求。
: import sys
: import json
: from sets import Set
: # Define an object hook function to check title
: def check_title(dct):
: if "title" in dct and type(dct["title"]) == unicode:
: titles.add(dct["title"])
: return dct
m*o
66 楼
用了龙太子的fastparse, collect函数是答案。注意把代码中的[back slash]去掉。这
个解法边parse json边收集结果,效
果应该比先parse完json再处理对应的dictionary/map要好一点。
import fastparse.all._
val space = P( CharsWhileIn(" \[back slash]r\[back slash]n").? )
val digits = P( CharsWhileIn("0123456789"))
val exponent = P( CharIn("eE") ~ CharIn("+-").? ~ digits )
val fractional = P( "." ~ digits )
val integral = P( "0" | CharIn('1' to '9') ~ digits.? )
val number = P( CharIn("+-").? ~ integral ~ fractional.? ~ exponent.? ).
map(_ => Set.empty[String])
val `null` = P( "null" ).map(_ => Set.empty[String])
val `false` = P( "false" ).map(_ => Set.empty[String])
val `true` = P( "true" ).map(_ => Set.empty[String])
val hexDigit = P( CharIn('0'to'9', 'a'to'f', 'A'to'F') )
val unicodeEscape = P( "u" ~ hexDigit ~ hexDigit ~ hexDigit ~ hexDigit )
val escape = P( "\[back slash]\[back slash]" ~ (CharIn("\[back
slash]"/\[back slash]\[back slash]bfnrt") | unicodeEscape) )
val strChars = P( CharsWhile(!"\[back slash]"\[back slash]\[back slash]".
contains(_: Char)) )
val string =
P( space ~ "\[back slash]"" ~/ (strChars | escape).rep.! ~ "\[back slash
]"")
val stringValue = string.map(Set(_))
def pair = (string ~/ ":" ~/ (stringValue.map(Left(_)) | expr.map(Right(_)
))) map { case (k, v) =>
if (k == "title") v.fold(identity, identity)
else v.fold(_ => Set.empty[String], identity)
}
def obj =
P( "{" ~/ pair.rep(sep=",".~/) ~ space ~ "}").map(_.reduce(_ union _))
def array =
P( "[" ~/ expr.rep(sep=",".~/) ~ space ~ "]").map(_.reduce(_ union _))
def expr : Parser[Set[String]]= P(
space ~ (obj | array | stringValue.map(_ => Set.empty[String]) | `true`
| `false` | `null` | number) ~ space
)
def collect(json: String): Set[String] =
expr.parse(json) match {
case Success(set, _) => set
case _ => Set.empty
}
【在 n***p 的大作中提到】
: 给一个json string。找出所有对应的key不重复的value。
: 比如输入以下string,找出所有“title"的value
: {
: "glossary":{
: "title":"example",
: "GlossDiv":{
: "title":"S",
: "GlossList":{
: "title":{
: "ID":"SGML",
个解法边parse json边收集结果,效
果应该比先parse完json再处理对应的dictionary/map要好一点。
import fastparse.all._
val space = P( CharsWhileIn(" \[back slash]r\[back slash]n").? )
val digits = P( CharsWhileIn("0123456789"))
val exponent = P( CharIn("eE") ~ CharIn("+-").? ~ digits )
val fractional = P( "." ~ digits )
val integral = P( "0" | CharIn('1' to '9') ~ digits.? )
val number = P( CharIn("+-").? ~ integral ~ fractional.? ~ exponent.? ).
map(_ => Set.empty[String])
val `null` = P( "null" ).map(_ => Set.empty[String])
val `false` = P( "false" ).map(_ => Set.empty[String])
val `true` = P( "true" ).map(_ => Set.empty[String])
val hexDigit = P( CharIn('0'to'9', 'a'to'f', 'A'to'F') )
val unicodeEscape = P( "u" ~ hexDigit ~ hexDigit ~ hexDigit ~ hexDigit )
val escape = P( "\[back slash]\[back slash]" ~ (CharIn("\[back
slash]"/\[back slash]\[back slash]bfnrt") | unicodeEscape) )
val strChars = P( CharsWhile(!"\[back slash]"\[back slash]\[back slash]".
contains(_: Char)) )
val string =
P( space ~ "\[back slash]"" ~/ (strChars | escape).rep.! ~ "\[back slash
]"")
val stringValue = string.map(Set(_))
def pair = (string ~/ ":" ~/ (stringValue.map(Left(_)) | expr.map(Right(_)
))) map { case (k, v) =>
if (k == "title") v.fold(identity, identity)
else v.fold(_ => Set.empty[String], identity)
}
def obj =
P( "{" ~/ pair.rep(sep=",".~/) ~ space ~ "}").map(_.reduce(_ union _))
def array =
P( "[" ~/ expr.rep(sep=",".~/) ~ space ~ "]").map(_.reduce(_ union _))
def expr : Parser[Set[String]]= P(
space ~ (obj | array | stringValue.map(_ => Set.empty[String]) | `true`
| `false` | `null` | number) ~ space
)
def collect(json: String): Set[String] =
expr.parse(json) match {
case Success(set, _) => set
case _ => Set.empty
}
【在 n***p 的大作中提到】
: 给一个json string。找出所有对应的key不重复的value。
: 比如输入以下string,找出所有“title"的value
: {
: "glossary":{
: "title":"example",
: "GlossDiv":{
: "title":"S",
: "GlossList":{
: "title":{
: "ID":"SGML",
n*p
67 楼
所有答案里有OOP吗?
n*7
68 楼
贴个C#的,test通过
对json处理不熟,我其实感觉用正则表达式抓一下就好了?
---
Code
---
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
namespace Mitbbs
{
public static class Utilities
{
public static IEnumerable FindUniqueValuesFromKey(string
json, string key) =>
ProcessJsonToken(JObject.Parse(json)).Where(x => x.Key == key).
Select(x => x.Value).Distinct();
private static IEnumerable
ProcessJsonToken(JToken jToken)
{
switch (jToken)
{
case JProperty jProperty:
return ProcessJsonProperty(jProperty);
case JArray jArray:
return jArray.Children().Select(ProcessJsonToken).
SelectMany(x => x);
case JObject jObject:
return jObject.Properties().Select(ProcessJsonToken).
SelectMany(x => x);
default:
return new(string, string)[] { };
}
}
private static IEnumerable
ProcessJsonProperty(JProperty jProperty)
{
switch (jProperty.Value.Type)
{
case JTokenType.String:
return new[] {(jProperty.Name, jProperty.Value.ToString(
))};
case JTokenType.Object:
case JTokenType.Property:
case JTokenType.Array:
return jProperty.Value.Children().Select(
ProcessJsonToken).SelectMany(x => x);
default:
return new (string, string)[] { };
}
}
}
}
---
Test
---
using Mitbbs;
using Xunit;
namespace Unittests
{
public class UtilitiesTests
{
private const string Json = @"{
'glossary':{
'title':'example',
'GlossDiv':{
'title':'S',
'GlossList':{
'title':{
'ID':'SGML',
'SortAs':'SGML',
'title':'S',
'Acronym':'SGML',
'Abbrev':'ISO 8879:1986',
'GlossDef':{ 'title': 'S'},
'GlossSee':[{'title': 'e.g.'}, {'another
': 'etc'}]
}
}
}
}
}";
[Fact]
public void FindUniqueValuesFromKey_AsExpected()
{
var expected = new[] { "example", "S", "e.g." };
Assert.Equal(expected, Utilities.FindUniqueValuesFromKey(Json, "
title"));
}
}
}
【在 n***p 的大作中提到】
: 所有答案里有OOP吗?
对json处理不熟,我其实感觉用正则表达式抓一下就好了?
---
Code
---
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
namespace Mitbbs
{
public static class Utilities
{
public static IEnumerable
json, string key) =>
ProcessJsonToken(JObject.Parse(json)).Where(x => x.Key == key).
Select(x => x.Value).Distinct();
private static IEnumerable
ProcessJsonToken(JToken jToken)
{
switch (jToken)
{
case JProperty jProperty:
return ProcessJsonProperty(jProperty);
case JArray jArray:
return jArray.Children().Select(ProcessJsonToken).
SelectMany(x => x);
case JObject jObject:
return jObject.Properties().Select(ProcessJsonToken).
SelectMany(x => x);
default:
return new(string, string)[] { };
}
}
private static IEnumerable
ProcessJsonProperty(JProperty jProperty)
{
switch (jProperty.Value.Type)
{
case JTokenType.String:
return new[] {(jProperty.Name, jProperty.Value.ToString(
))};
case JTokenType.Object:
case JTokenType.Property:
case JTokenType.Array:
return jProperty.Value.Children().Select(
ProcessJsonToken).SelectMany(x => x);
default:
return new (string, string)[] { };
}
}
}
}
---
Test
---
using Mitbbs;
using Xunit;
namespace Unittests
{
public class UtilitiesTests
{
private const string Json = @"{
'glossary':{
'title':'example',
'GlossDiv':{
'title':'S',
'GlossList':{
'title':{
'ID':'SGML',
'SortAs':'SGML',
'title':'S',
'Acronym':'SGML',
'Abbrev':'ISO 8879:1986',
'GlossDef':{ 'title': 'S'},
'GlossSee':[{'title': 'e.g.'}, {'another
': 'etc'}]
}
}
}
}
}";
[Fact]
public void FindUniqueValuesFromKey_AsExpected()
{
var expected = new[] { "example", "S", "e.g." };
Assert.Equal(expected, Utilities.FindUniqueValuesFromKey(Json, "
title"));
}
}
}
【在 n***p 的大作中提到】
: 所有答案里有OOP吗?
T*x
71 楼
这两天碰到一个json问题,有了答案,突然想起本版的这道题,就把自己的答案post上
来。我这个用到了一个“json path”的概念,和xpath差不多,和其他的tree path也
差不多。这算是解决此类问题的一个一般性方法吧。
来。我这个用到了一个“json path”的概念,和xpath差不多,和其他的tree path也
差不多。这算是解决此类问题的一个一般性方法吧。
相关阅读
问个GSL的问题匹配问题 (转载)这是怎么回事?关于void指针Help: who has gcc 4.0 or higher一道面试怪题C++. (转载)perl里面的seek怎么用呢?C++里面哪里能找到2005版“Solaris system programming“电子版?Perl programming请教C++ 进阶问题where can I get this book?what's the difference请教大家一个问题Perl programming请教有没有tkcvs的简易上手指南? (转载)关于effective c++的几个问题如何在Windows的console内输出彩色的字符(内空),多谢!How to do this? Please help!Quick Question about perl module