Nushell:将记录列表转换为表

Nushell:将记录列表转换为表

消歧注释:我最初将其命名为“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

不幸的是我对nushell 不熟悉。不过,您绝对可以将数据作为 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     │
╰───┴─────────┴─────────────────────────┴───────────────╯

相关内容