英文:
How to remove seq of array elments matching a pattern at the beginning and the end?
问题
我想删除每对 ["X"]
和 ["Y"]
之间的所有内容。我该如何做?
英文:
Suppose that I have a json file, in which the following pattern appears many times.
... [ ... ["X"], ... ,["Y"] ... ] ...
I want to remove everything between each pair of ["X"]
and ["Y"]
. How can I do it?
答案1
得分: 1
代码部分不要翻译,只返回翻译好的部分:
这个问题似乎有两个部分:
(1) 给定一个数组,如何删除所有由两个值“包围”的段落?
(2) 给定一个单个的JSON实体(也称为文档),如何在文档中的任何位置执行上述删除操作?
在这里,我将提供一个针对第一个部分(1)的替代方案,并展示如何将其应用于整个JSON实体。
以下是替代方案,它具有不对$ x和$ y值的出现做出强烈假设的可能优势,并允许关于删除书本末端本身的两种解释:
# 输入:一个数组
# 删除从$x到下一个$y的所有连续段,同时删除两个书本末端,如果且仅如果$bookends。
# 必须同时存在两个书本末端才能删除一个连续段。
def remove_all_xy($x; $y; $bookends):
# 辅助函数,如果有的话,从$x到$y中移除一个连续段
def r:
index($x) as $ix
| if $ix then .[$ix+1:] as $tail
| ($tail | index($y)) as $iy
| if $iy
then (if $bookends then 0 else 1 end) as $adjust
| .[:$ix + $adjust] + ($tail | .[1+$iy - $adjust:] | r)
else . end
else . end;
r;
现在假设您决定使用某个函数,foo($x;$y;$bookends)
,来执行每个数组操作。要将其应用于整个文档,可以编写:
walk(if type == "array" then foo($x;$y;$bookends) else . end)
这可能不是尽可能高效的方法,但在实践中应该足够。如果不够高效,那么只需调整标准的walk
函数即可。
英文:
The question seems to have two components:
(1) Given an array, how can I delete all segments that are "bookended" by two values?
(2) Given a single JSON entity (aka document), how can I perform the above-mentioned deletion operation on all arrays, no matter where they occur within the document?
Here, I will offer an alternative to @pmf's solution for (1) and show how to apply it to an entire JSON entity.
Here's the alternative, which has the possible advantage that it doesn't make any strong assumptions about the occurrence of the $x and $y values, and allows for both interpretations regarding the removal of the bookends themselves:
# Input: an array
# Remove all stretches from $x to the next $y,
# removing both bookends too if and only if $bookends.
# Both bookends must be present for a stretch to be removed.
def remove_all_xy($x; $y; $bookends):
# The helper function removes a single stretch from $x to $y, if any
def r:
index($x) as $ix
| if $ix then .[$ix+1:] as $tail
| ($tail | index($y)) as $iy
| if $iy
then (if $bookends then 0 else 1 end) as $adjust
| .[:$ix + $adjust] + ($tail | .[1+$iy - $adjust:] | r)
else . end
else . end;
r;
Now let's say you decide on some function, foo($x;$y;$bookends)
, for performing the per-array operation. To apply it to the whole document,
you could write:
walk(if type == "array" then foo($x;$y;$bookends) else . end)
This might not be as efficient as possible, but in practice it should suffice. (If not, then simply adapt the standard walk
.)
答案2
得分: 0
假设成对出现,并且“between”表示排除边界项,您可以查询边界项的indices
,并获取它们之间的所有内容。
给定以下示例,以下筛选器将生成以下输出:
[
["A"], ["B"], ["X"], ["C"], ["D"], ["Y"], ["E"], ["F"],
["G"], ["H"], ["X"], ["I"], ["J"], ["Y"], ["K"], ["L"]
]
[
(
[[indices(["X"]), indices(["Y"])] | 0, transpose[][], infinite]
| _nwise(2)
)
as [$a, $b] | .[$a:$b+1][]
]
[["A"],["B"],["X"],["Y"],["E"],["F"],["G"],["H"],["X"],["Y"],["K"],["L"]]
如果边界项可以以任何顺序出现,并且不一定以相等数量出现,在对两个索引列表进行转置之前,它们需要首先被过滤,以仅包含相互连续的位置。
英文:
Assuming pairwise occurrences, and that "between" means excluding the border items, you could query the indices
of the border items, and fetch everything in between.
Given the following sample, the following filter will produce the following output:
[
["A"], ["B"], ["X"], ["C"], ["D"], ["Y"], ["E"], ["F"],
["G"], ["H"], ["X"], ["I"], ["J"], ["Y"], ["K"], ["L"]
]
[
(
[[indices([["X"]]), indices([["Y"]])] | 0, transpose[][], infinite]
| _nwise(2)
)
as [$a, $b] | .[$a:$b+1][]
]
[["A"],["B"],["X"],["Y"],["E"],["F"],["G"],["H"],["X"],["Y"],["K"],["L"]]
If the border items may occur in any order, and not necessarily in equal amounts, before transposing the two lists of indices they would need to be filtered first to only contain mutually successive positions.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论