展开数组


34

这个挑战是由有关Mathematica.SE的一个问题引起的

假设您有一些任意结构的嵌套列表/数组(每个级别的列表不一定具有相同的长度)。为简单起见,我们假设节点是非负整数或空数组。举个例子

[[[1, 3], 2], [1, 4], 12, [[0, [], 0], [5, [7]]]]

有时,将列表展平以对节点执行一些操作更为方便,例如

--> [1, 3, 2, 1, 4, 12, 0, 0, 5, 7]
--> [1, 1, 0, 1, 0, 0, 0, 0, 1, 1]

但是最后,您实际上想要保留原始结构,因此您想将其转换为

--> [[[1, 1], 0], [1, 0], 0, [[0, [], 0], [1, [1]]]

您的任务是执行最后一步。

给定一个嵌套的任意非负整数的列表(表示结果的所需结构),以及一个非负整数的平面列表(表示所需的值),将平面列表重新构造为结构化列表的形式。您可以假定两个列表都包含相同数量的整数。

像往常一样,您不必处理无效的输入(例如,第二个列表不是平坦的,输入在语法上是不正确的,没有整数作为节点,等等)。您可以在代码中修改输入数组。

您可以编写函数或程序,通过STDIN,命令行参数或函数参数获取输入,还可以返回结果或将结果打印到STDOUT。您可以使用任何方便的列表或字符串格式来表示输入和输出(只要格式是明确的并且输入未经预处理)。另外,两个输入的格式必须一致(例如,您不能将一个输入作为字符串,而将另一个输入作为列表)。您可以按照任何顺序输入列表,但是请在答案中指定确切的输入方法。

另一个限制:不得使用正则表达式。这是一个数组操作挑战,而不是字符串操作挑战。

这是代码高尔夫球,因此最短的答案(以字节为单位)获胜。

测试用例

Structure                             Values                 Result
[[[1,3],2],[1,4],12,[[0,0],[5,[7]]]]  [1,1,0,1,0,0,0,0,1,1]  [[[1,1],0],[1,0],0,[[0,0],[1,[1]]]]
[[[0,0],0],[0,0],0,[[0,0],[0,[0]]]]   [1,1,0,1,0,0,0,0,1,1]  [[[1,1],0],[1,0],0,[[0,0],[1,[1]]]]
[]                                    []                     []
[[]]                                  []                     [[]]
[0,1,2,3]                             [5,1,0,5]              [5,1,0,5]
[[[[[0]]]]]                           [123]                  [[[[[123]]]]]
[0,[1,[]],[[]],[2,3],[]]              [1,6,1,8]              [1,[6,[]],[[]],[1,8],[]]

如果Structure数组中的值被更改,是否允许?
ProgramFOX 2015年

@ProgramFOX是的。“您可以在代码中修改输入数组。”
马丁·恩德

具有讽刺意味的是,这里的论文之一是在Mathematica中。
伊西亚·梅多斯

1
@impinball这是我的问题,我将其与问题一同发布,以防止其他人从链接的问题中窃取答案(实际上,这只是该问题的简化版本)。
马丁·恩德

@MartinBüttner哦。真好 实际上,这也是较短的答案之一。
伊西亚·梅多斯

Answers:


9

CJam,18 16 13字节

lA,sNerN%l~]z

通过STDIN以与先前的CJam答案相同的格式进行输入:

[0 [11 []] [[]] [2 3] []]
[1 6 1 8] 

并将结果字符串输出到STDOUT

[1 [6 []] [[]] [1 8] []]

我只是将第一行视为字符串,将所有数字字符转换为换行符,对一个或多个换行符进行分割,将第二行作为数组放在堆栈中,包装成一个数组并将两个数组(行)压缩在一起。打印是自动的,并且由于第一行被视为字符串,因此保留了方括号。

代码扩展

lA,sNerN%l~]z
l                     "Read the first line of input. This is the nested array";
 A,s                  "Get array [0,1,2...9] and  convert it to string '012..9'";
    Ner               "Replace all occurrences of 0,1,2,..9 with new line";
       N%             "Split on one or more occurrences of new line";
         l~           "Read the second line as an array";
           ]          "Wrap both the splitted string and the second line array";
                      "in an array";
            z         "Transpose the array, there by placing the numbers from second";
                      "input array in the split holes of first input string";

感谢@ user23013节省了3个字节。

在这里在线尝试


在OP中,“这是一个数组操作挑战,而不是字符串操作挑战。”
2015年

@atk:这是有争议的,因为OP仅显式禁止正则表达式。
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ 2015年

1
简称/La-%
jimmy23013 2015年

@ user23013哇,从来没有想过也要%拆分,它也可以拆分多个事件!
Optimizer

@atk是的,因为只禁止了正则表达式,所以我使用了此技术。
Optimizer

25

JavaScript,ES6、44字节

f=(a,b,i=0)=>a.map(x=>x.map?f(x,b,i):b[i++])

这创建了一个f可以像

f([0,[1,[]],[[]],[2,3],[]],[1,6,1,8])

即嵌套数组和值数组作为输入参数。函数的输出是转换后的嵌套数组。

这个问题对于递归来说是一个非常好的问题,这就是为什么答案是一个简洁而又甜美的递归函数。我创建了f一个使用该map方法转换第一个参数的函数。对于每个元素,如果该元素是一个数组,它将f再次调用,否则,对于整数,它将获取第i 项并返回该项,并递增的值ii在每个递归调用中将的值向下传递,以保持顺序正确。

再次使用该map方法完成了数组与整数检测。对于数组变量,map是有效函数,而对于整数变量,则没有map为该变量定义的属性或函数。

这可在最新的Firefox浏览器中使用(由于ES6)。


3
我知道我应该避免使用诸如“ +1”和“感谢”之类的注释,但是该死的,这是一个不错的ES6功能!我可以在这行代码中看到几个小时了:)
雅各布(Jacob)

我认为.map代码中存在2个。有什么办法可以进一步缩短它?无论如何,不​​错的代码!
德里克·朕会功夫,2014年

哇,ES何时添加了lambda语法?
蓬松的2014年

@fluffy in ES6;)
Optimizer

@Derek朕会功夫幸好没有。map与上下文相关,因此第一个映射属于该迭代映射,a而下一个映射则属于每个映射x。没有其他更短的方法可以引用map或区分数组和整数
Optimizer

18

JavaScript,ES6、41个字节

Optimizer的回答给我留下了深刻的印象,它做得非常巧妙,我学到了很多东西。但是,在查看它时,我发现了一种将其略微缩短并修复一个小错误的方法:

f=(a,b)=>a.map(x=>x.map?f(x,b):b.shift())

我取出i变量,并用替换了它shift()。这使得它略短一些,并解决了以下问题:i按值而不是按引用传递,女巫导致最终数组中的某些数字重复,而最后一些不使用。再说一次,Optimizer的答案确实经过深思熟虑,比我可以做的要好,我只做了一点修正。


2
高尔夫不错!令我感到遗憾的是:P
Optimizer

16

Dyalog APL,14个字符

这是一个没有脑子:(∊a)←b

通常,∊a意味着a扁平化,但是当它出现在作业的左侧时,它恰好可以解决此问题的要求。为了符合成为函数的要求,它需要一些额外的花样:({a←⍺⋄(∊a)←⍵⋄a}为lambda 以及为左右参数提供的花括号;为语句分隔符提供的花括号)。

测试上tryapl.org。请注意,在APL中,空数值向量由(“ zilde”)表示。使用一元素向量构造,(,A)因为(A)这意味着标量。在输出中,这件事:

┌⊖┐
│0│
└~┘

代表一个空的数值向量。所述0在中央示出了“原型元件”,这是不是数组的元素。


1
这是否图形表示不区分(,1)(1)为什么是最后一位刚刚提出的[1|1],而不是[1|[1]]
Martin Ender 2014年

tryapl使用的图形表示形式(称为]box on)无法区分它们。Dyalog中的另一个函数(displayfrom dfns.dws)确实有所区别,但不幸的是tryapl限制了其他工作空间(即库)的加载。:(
ngn 2014年

1
要以方括号形式查看结果,请尝试以下操作:∊{0=⍴⍴⍵:⍕⍵ ⋄ '['(∇¨⍵)']'}a。或这样:∊{0=⍴⍴⍵:⍕⍵ ⋄ '['(1↓,'|',[1.5]∇¨⍵)']'}a如果您坚持使用分隔符,|
ngn 2014年

哦,您也可以]display a在tryapl中使用。它提供了有关结构的完整信息。抱歉,我最初没有意识到这一点。
ngn 2014年

有道理。我把它变成一个函数,但要多花2个字节。
ngn 2014年

10

Python,51岁

f=lambda a,b:[b.pop(0)if x<[]else f(x,b)for x in a]

例:

>>> f([0,[1,[]],[[]],[2,3],[]], [1,6,1,8])
[1, [6, []], [[]], [1, 8], []]

10

python 2,50

f=lambda s,v:v.pop(0)if s<[]else[f(x,v)for x in s]

这是一个非常美丽的问题。在我继续努力的过程中,我不断意识到我的代码是不必要的,并且逻辑崩溃成了一个简单的表达式。大部分高尔夫运动都是在寻找正确的算法。

s是结构,v是列表的平面列表。这个想法是检查是否s为整数s<[](Python 2将数字视为小于列表)。如果是的话,只需获取并返回的第一个元素v,将其从中删除v。否则,递归到的子列表s

pop 在非常实用的代码中,这是命令式魔术。因为所有v指向同一实例,所以从一个实例中弹出一个元素会将其从v整个执行树中删除,因此in中的每个数字v仅使用一次。列表推导[f(x,v)for x in s]会创建一个调用树,该调用树按深度优先和从左至右的v顺序展开,从而使的元素按正确的顺序排列。

我编写此代码与grc的答案无关,但事实证明,直到移动单个[(和变量名)相同。由于间距,此举可节省字符。括号移动意味着立即在函数中处理节点大小写,而不是作为列表理解的一部分,我没有考虑过。

如果我们扩展输入要求以将来自STDIN和结构的值用作函数参数,则可以将char保存为49。这让我们可以使用map

v=input()
g=lambda s:v.pop(0)if s<[]else map(g,s)

9

红宝石,39岁

f=->a,b{a.map{|d|f[d,b]}rescue b.shift}

递归直到列表中的元素为整数。
由于调用Integer.map会给出异常,
因此它进入了急救部分,该部分将第一个元素“弹出/移出”第二个列表。

正则表达式解决方案...更长一点:

f=->a,b{eval a.to_s.split(/\d+/).zip(b)*''}

尝试一些测试用例


仅供参考,不允许使用正则表达式解决方案。;)
Martin Ender 2014年

5

CJam,43 37 35 33字节

这是我的JS答案的直接转换。有点长,其中大多数由类型检测占用。

q~:B;{{_`La`&{F}{;BW):W=}?}%}:F~`

像这样在STDIN的两行上取两个输入数组

[[[1 3] 2] [1 4] 12 [] [[0 0] [5 [7]]]]
[1 1 0 1 0 0 0 0 1 1]

并输出到STDOUT像

[[[1 1] 0] [1 0] 0 "" [[0 0] [1 [1]]]]

在这里在线尝试


5

Haskell,113104字节(数据类型声明中为86 + 18)

data N=I Int|L[N]
L[]!v=(L[],v)
L(a:b)!v|(c,w)<-a!v,(L d,u)<-L b!w=(L$c:d,u)
_!(n:m)=(I n,m)
s#v=fst$s!v

Haskell没有内置的嵌套数组数据类型,因此我不得不自己动手。因此,该程序仅包含模式匹配和显式结构递归。最后一个测试用例为

L[I 0,L[I 1,L[]],L[L[]],L[I 2,I 3],L[]]#[1,6,1,8]

并评估为

L[I 1,L[I 6,L[]],L[L[]],L[I 1,I 8],L[]]

4

Mathematica,41个字节

Function[,m[[i++]],Listable][i=1;m=#2;#]&

这是一个未命名的函数,该函数将结构作为第一个参数,并将值列表作为第二个参数(并返回一个列表)。

这是引发该挑战的问题的已接受答案的高尔夫版本。我自己发布了此信息,并且不会接受此答案(我是否应该将其实际上保持为最短)?这是为了防止其他人通过基本上复制答案来赢得挑战。

怎么运行的:

  • 我们定义一个Listable纯函数。可列出函数会自动(递归地)应用于列表参数的元素,而不是列表本身,因此调用f结构化列表将基本上返回具有相同结构的列表,其中每个整数i都由代替f[i]
  • 我们将值列表存储在全局变量中,m并将计数器存储在中i
  • 每次调用时f(无论参数如何),我们都会返回的下一个元素m

4

Rebol- 87 66 60

f: func[a[block!]b][map-each n a[any[attempt[f n b]take b]]]

取消高尔夫:

f: func [a [block!] b] [
    map-each n a [
        any [
            attempt [f n b]  
            take b
        ]
    ]
]

例:

>> f [0 [1 []] [[]] [2 3] []]   [1 6 1 8]           
== [1 [6 []] [[]] [1 8] []]

4

C#,225 + 13 = 239185 + 35 = 220172 + 35 = 207字节

需要以下内容:

using System;using o=System.Object;

接受object[]s作为参数。

o[]u(o[]a,o[]b){var c=a;int i=0;Action<o[],o[]>d=null;d=(e, f)=>{for(int j=0;j<e.Length;j++){if(e[j]is int){f[j]=b[i];i++;}else{d((o[])e[j],(o[])f[j]);}}};d(a,c);return c;}

取消程式码:

object[] Unflatten(object[] structure, object[] values)
{
    var c = structure;
    int i = 0;
    Action<object[], object[]> recursiveFunc = null;
    recursiveFunc = (e, f) =>
    {
        for (int j = 0; j < e.Length; j++)
        {
            if (e[j] is int)
            {
                f[j] = values[i]; i++;
            }
            else
            {
                recursiveFunc((object[])e[j], (object[])f[j]);
            }
        }
    };
    recursiveFunc(structure, c);
    return c;
}

2
您可以通过缩短多一点using o=System.Object和更换的所有实例object与简单omsdn.microsoft.com/en-us/library/sf0df423.aspx
Kroltan 2015年

1
@Kroltan大提示,谢谢!
ProgramFOX

Clone很浅 如果允许修改输入,则根本不需要克隆。如果不允许,则需要正确的克隆。
CodesInChaos

我看到了@CodesInChaos。由于允许修改输入数组,因此删除了克隆。谢谢!
ProgramFOX

3

Python 2,64字节

def g(N,L):f=lambda N:L.pop(0)if`N`<":"else map(f,N);return f(N)

我听说您喜欢列表中的列表,所以我将函数放在函数中。

编辑:现在看grc的答案,我意识到那是完全没有必要的。那好吧...


3

SWI-Prolog 82

f([],A,[],A):-!.
f([H|T],A,[J|U],B):-(is_list(H),!,f(H,A,J,C);A=[J|C]),f(T,C,U,B).

样品运行:

?- f([[[1,3],2],[1,4],12,[[0,[],0],[5,[7]]]],[1,1,0,1,0,0,0,0,1,1],R,[]).
R = [[[1,1],0],[1,0],0,[[0,[],0],[1,[1]]]].

[]查询中的最后一个用于检查元素数量不匹配,在这个问题中似乎没有必要。


是什么使得削减开支(以及由此而导致的昂贵开支is_list)成为必要?
不相关的字符串

1
@UnrelatedString:如果发现不需要正确答案,可以直接直接编辑答案。那时,我的Prolog很糟糕(我使用了库并进行了广泛的削减),如今这些日子甚至更加生锈。
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

2

Erlang,116 93字节

f(R,F)->put(n,F),[g(X)||X<-R].
g([H|T])->[g(H)|g(T)];g([])->[];g(E)->[H|T]=get(n),put(n,T),H.

使用两个不纯函数fgf通过设置n为平面列表来操作流程字典,并将嵌套列表的每个元素映射到g(X)g然后n,在遇到非列表值时,将其设置到平面列表的末尾,并返回平面列表的开头。


1

Perl 5,49个字节

第一个参数是模板结构,第二个是值。

sub u{($t,$l)=@_;ref$t?[map{u$_,$l}@$t]:shift@$l}

测试程序

use Test::More;
use Test::Deep;

sub u{($t,$l)=@_;ref$t?[map{u$_,$l}@$t]:shift@$l}

cmp_deeply u([[[1,3],2],[1,4],12,[[0,0],[5,[7]]]],[1,1,0,1,0,0,0,0,1,1]),[[[1,1],0],[1,0],0,[[0,0],[1,[1]]]];
cmp_deeply u([[[0,0],0],[0,0],0,[[0,0],[0,[0]]]],[1,1,0,1,0,0,0,0,1,1]),[[[1,1],0],[1,0],0,[[0,0],[1,[1]]]];
cmp_deeply u([], []), [];
cmp_deeply u([[]], []), [[]];
cmp_deeply u([0,1,2,3], [5,1,0,5]), [5,1,0,5];
cmp_deeply u([[[[[0]]]]], [123]), [[[[[123]]]]];
cmp_deeply u([0,[1,[]],[[]],[2,3],[]], [1,6,1,8]), [1,[6,[]],[[]],[1,8],[]];
done_testing;

1

动力壳:115

输入数组为$ i,映射为$ m,输出为$ o

$h={if($_.GetType().IsArray){if($_.c -eq 0){,@()}else{,@($_|%{.$h})}}else{$m[$c++]}};$i|%{$o=@();$c=0}{$o+=,(.$h)}

$ h是包含递归函数的字符串,您可以使用。$ h执行字符串中包含的代码。如果powershell不坚持将单值数组和标量平面化,则它将缩短30个字节。将单个null值设置为null

以及方便的数组结构查看器,用于验证结果

$j={if($_.GetType().IsArray){write-host '(' -n;($_|%{.$j});write-host ')' -n}else{write-host "$_" -n}};write-host '(' -n;$o|%{(.$j)}; write-host ')' -n;

编辑:149

另存为unflatten.ps1:

$m=[array]$args[1];$h={if($_.GetType().IsArray){if($_.c -eq 0){,@()}else{,@($_|%{.$h})}}else{$m[$c++]}};$args[0]|%{$o=@();$c=0}{$o+=,(.$h)};echo $o;

编辑:136,内联输出数组的创建和写入输出

$m=[array]$args[1];$h={if($_.GetType().IsArray){if($_.c -eq 0){,@()}else{,@($_|%{.$h})}}else{$m[$c++]}};echo(,@($args[0]|%{$c=0}{.$h}))

用。\ unflatten.ps1调用[输入数组] [映射数组]

输出被写入管道-因此请首先运行:

Function View-Array{
Param([Parameter(ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)]
      [array]$o)

    PROCESS{
    $j={if($_.GetType().IsArray){write-host '(' -n;($_|%{.$j});write-host ')' -n}else{write-host "$_" -n}};
    write-host '(' -n;$o|%{(.$j)}; write-host ')' -n;
    }
}

并与

.\unflatten.ps1 [input array] [mapping array] | View-Array

1

C#,(40 + 123)= 163字节或(67 + 81)= 148字节

C#在此遭受其静态类型和长名称空间的困扰。

数组方法

使用语句:

using o=System.Object;using System.Linq;

码:

o[] u(o[] x,o[] y){int i=0;Func<o[],o[],o[]> f=null;f=(a,b)=>a.Select(e=>e is int?b[i++]:f((o[])e,b)).ToArray();return f(x,y);}

堆叠方式(使用堆栈结构而不是数组)

使用语句:

using s=System.Collections.Generic.Stack<object>;using System.Linq;

码:

System.Func<s,s,s>f=null;f=(a,b)=>new s(a.Select(e=>e is int?b.Pop():f((s)e,b)));

第一次尝试,这里首先打高尔夫。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.