消歧注释:我最初将其命名为“Nushell:将列表转换为表格”(某些搜索引擎将其作为这些单词的第一个结果),但是这个堆栈溢出问题可能是一个更好的“列表到表格”的例子。
Nushell 中是否有一种惯用的方法将类似记录列表转换为表格?
我正在与堆栈交换API并得到如下结果:
let questions = ('[
{
"tags":
[
"nushell"
],
"title": "Nushell: Convert list to table"
},
{
"tags":
[
"ssh",
"tar"
],
"title": "tar through ssh session",
"closed_reason": "Duplicate"
}
]' | from json)
请注意,closed_reason
当然,仅针对已关闭的问题返回。这是有道理的——API 不需要浪费带宽来为大多数问题返回空字段。
但结果,$questions
就变成了Nushell中的一个list<any>
。这意味着像这样的操作:
> $questions | group-by closed_reason
...导致(逻辑上)cannot find column
错误。
所有结果都需要具有相同的结构才能实现此目的。例如,如果所有结果都有closed_reason
's,如下所示:
let questions = ('[
{
"tags":
[
"nushell"
],
"title": "Nushell: Convert list to table",
"closed_reason": ""
},
{
"tags":
[
"ssh",
"tar"
],
"title": "tar through ssh session",
"closed_reason": "Duplicate"
}
]' | from json)
那么就$questions | describe
变成:
table<tags: list<string>, title: string, closed_reason: string>
并且$questions | group-by closed_reason
会起作用。
有什么方法可以将列表转换/“规范化”为表格吗?
我已经尝试过(使用原始list<any>
结果):
> $questions | table | group-by closed_reason
# obviously doesn't work, since the table command is just for rendering
# but worth a shot
> $questions | to csv | from csv | group-by closed_reason
# works, but loses the tag lists
> $questions | transpose | transpose | headers | reject column0 | to json
# Almost works, but still results in a list<any>
# since the first question's closed_reason becomes null
> $questions | transpose | transpose | headers | reject column0 | group-by closed_reason
# results in "can't convert nothing to string"
答案1
您现在可以使用问号运算符,如官方中所述文档:
❯ $questions | group-by closed_reason?
╭───────────┬───────────────────────────────────────────────────────────────╮
│ │ ╭───┬─────────────┬─────────────────────────┬───────────────╮ │
│ Duplicate │ │ # │ tags │ title │ closed_reason │ │
│ │ ├───┼─────────────┼─────────────────────────┼───────────────┤ │
│ │ │ 0 │ ╭───┬─────╮ │ tar through ssh session │ Duplicate │ │
│ │ │ │ │ 0 │ ssh │ │ │ │ │
│ │ │ │ │ 1 │ tar │ │ │ │ │
│ │ │ │ ╰───┴─────╯ │ │ │ │
│ │ ╰───┴─────────────┴─────────────────────────┴───────────────╯ │
╰───────────┴───────────────────────────────────────────────────────────────╯
答案2
不幸的是我对nu
shell 不熟悉。不过,您绝对可以将数据作为 JSON 传递到jq
,使用空字符串值添加缺少的键,然后将其转换回 shell 的内部表示形式。
在这里,我正在更新questions
变量,但您可以将jq
命令标记到原始let
命令上,而不是不必要地来回转换数据。
let questions = ($questions | to json | jq '.[].closed_reason += ""' | from json)
然后您可以按以下方式对其进行分组closed_reason
:
〉$questions | group-by closed_reason
╭───────────┬───────────────╮
│ │ [table 1 row] │
│ Duplicate │ [table 1 row] │
╰───────────┴───────────────╯
答案3
终于找到了答案。help --find def
当我发现适当命名的(但在 Nushell 书中没有引用)命令时,我碰巧正在寻找完全不同的东西,default
该命令本质上是一个 Nushell 内置命令,用于执行与@Kusalananda 推荐和jq
。
因此问题中的示例可以通过以下方式修复:
> $questions | default "" closed_reason | group-by closed_reason
╭───────────┬───────────────╮
│ │ [table 1 row] │
│ Duplicate │ [table 1 row] │
╰───────────┴───────────────╯
结果是一个真正的 Nushell 表对象:
> $questions | default "" closed_reason | describe
table<tags: list<string>, title: string, closed_reason: string>
有了这些,我就可以开始在 Stack API 上进行一些切片和切块了:
> $questions |
default "" closed_reason |
where closed_reason == "Duplicate" |
update tags { $in.tags | str collect ','}
╭───┬─────────┬─────────────────────────┬───────────────╮
│ # │ tags │ title │ closed_reason │
├───┼─────────┼─────────────────────────┼───────────────┤
│ 0 │ ssh,tar │ tar through ssh session │ Duplicate │
╰───┴─────────┴─────────────────────────┴───────────────╯