枚举数组,将重复项分组


24

这项挑战的目的是采用正整数数组,并枚举其索引,将类似的元素分组。

通过仅输出对数组((value, index)例如[3, 4, 13, 9, 2]=>)来完成没有任何重复项的枚举[[3,1],[4,2],[13,3],[9,4],[2,5]]

但是,如果给定元素第二次出现,则不会给它自己的对,而是添加到第一次出现的组中。如果在上面的示例中将9替换为3,则在输出中将删除[9,4]并替换[3,1][3,1,4]

在输出中,组必须按其第一次出现的顺序进行排序,并且索引必须按升序排列。该元素必须在组中的第一个,然后是其索引。输出可能是0或1索引。您可以假设该数组至少包含一个元素。

测试用例:

Input           | Output (One-indexed)
[3, 2, 2, 3]    | [[3, 1, 4], [2, 2, 3]]
[17]            | [[17, 1]]
[1, 1]          | [[1, 1, 2]]
[1, 1, 2]       | [[1, 1, 2], [2, 3]]
[1, 2, 3, 4]    | [[1, 1], [2, 2], [3, 3], [4, 4]]
[1, 1, 1, 1]    | [[1, 1, 2, 3, 4]]

这是,最少字节获胜!


将索引以字符串形式输出是否可以接受,例如[[17,"1"]]?(尚不知道我是否可以那样保存任何字节,仍在处理!)
Shaggy

@shaggy当然,那很好
Pavel


1
我们可以[[3, [1, 4]], [2, [2, 3]]]代替输出吗?
Conor O'Brien

1
@Pavel没有理由:p但可以肯定
Conor O'Brien

Answers:


9

Dyalog APL,5个字节

(⊂,)⌸

在线尝试!

,⌸2字节几乎可以用,但是尾随零:/


这到底是做什么的?
Xcoder先生18年

@ Mr.Xcoder获取每个事物的索引,并使用事物和存在它的索引调用左运算符
dzaima

由于isue带有,⌸尾随零,并且零永远不会出现在输入中,是否有可能将所有零丢弃到少于3个字节中?
帕维尔

@Pavel存在零的原因是结果是一个矩阵,它必须具有精确的尺寸,因此只有1个字节可以丢弃任何字节增益的零。我觉得这也许可以打高尔夫球。
dzaima

2
“ fancy af”数组输出格式:在线尝试!
亚当

7

J,12个字节

~.,&.><@I.@=

零索引。

在线尝试!

如果可以删除我正在使用盒子进行的所有工作,则可以将字节数减少很多。我将看看是否可以解决。

说明

这可能还为时过早,无法解释(应该有更多的高尔夫运动)。

~. ,&.> <@I.@=
             =  Self-classify (comparison of each unique element to array)
            @   Composed with
          I.    Indices of ones (where it's equal)
         @      Composed with
        <       Boxed (how we deal with arrays of unequal length)
   ,&.>         Joined with
      >          Unbox each
   ,             Concatenate
    &.           Box again
~.              Unique elements

2
该阵列的输出格式,就是看中了AF
帕维尔

@Pavel也要占用很多字节Π.Π–
cole

5

05AB1E,10个字节

ÙεDIQƶ0K)˜

在线尝试!

说明

Ù             # remove duplicates
 ε            # apply to each element
  D           # duplicate
   IQ         # compare for equality with input
     ƶ        # multiply each element by its index (1-based)
      0K      # remove zeroes
        )˜    # wrap in a flattened list



5

附件,15字节

Flat=>Positions

在线尝试!

这是的一个有趣情况=>,是的运算符形式Map。当给定两个函数参数fand时gMap返回一个函数f => g[x]over x。也就是说,将RHS应用于输入,然后映射LHS。

内建函数Positions生成一个数组,该数组表示按索引进行的条目分组。默认情况下,当不提供第二个参数时,Positions将使用第一个参数。Flat然后将其映射到每个项目,这就是问题的要求。

替代解决方案

31个字节

MapArgs[Concat#~Indices,Unique]

在线尝试!

一个很短的,无内置的替代方案。MapArgs是一个类似的函数Map,除了您可以向其中输入其他参数。例如,MapArgs[{_1 + _2}, 1..3, 3][4, 5, 6]。像一样Map,当提供两个函数参数时,它变得很咖喱。要映射的函数是Concat#~Indices,这是一个fork。此派生应用于Unique输入项和输入本身。这转化为Concat[_, Indices[_2, _]](具有的参数Indices交换通过~),其对所述元件被映射(_)与所述元件的索引_输入数组,这是在_2(如ffed通过MapArgs)。

43字节

{Flat=>Zip[Unique[_],Indices[_,Unique[_]]]}

在线尝试!

实际上,这只是解决方案#1和#2的更详细(但更易读)组合。


4

果冻,6个字节

Q;"ĠṢ$

在线尝试!

说明:

Q;"ĠṢ$
Q      Keep the first occurrence of each element
     $ Last two links as a monad
   Ġ    Group indices of equal elements, then sort the resulting list of groups by the element they point to
    Ṣ   Sort; used to re-order the list of groups based on first occurrence instead
  "    Vectorize link between two arguments (the first occurrences and the group list)
 ;      Concatenate

在最后一个测试用例中不起作用。该数组应嵌套在另一层,输出始终是二维的。
帕维尔

@Pavel 是的,我只是忘了添加页脚(答案是一个函数)
Egg the Outgolfer

好吧,冷静。很快解释,是吗?:P
帕维尔

@Pavel添加了解释
暴民埃里克(Erik the Outgolfer)

4

Pyth,7个字节

0索引。

{+VQxRQ

在这里尝试! 另类。

怎么样?

{+ VQxRQ –完整程序。

     RQ –对于每个元素...
    x –获取所有索引。
 + V –并应用矢量化串联。
   Q –输入。
{–重复数据删除。

4

MATL,8字节

u"@tG=fh

MATL Online上尝试

说明

        # Implicitly get the input
u       # Compute the unique values
"       # For each unique value, N
  @     # Push the value N to the stack
  t     # Duplicate N
  G     # Grab the input
  =f    # Get the 1-based indices of the elements that equal N
  h     # Horizontally concatenate N with the indices
        # Implicitly display the result

太聪明了!我有18个字节试图使用,&f但从未成功。
朱塞佩

3

实际上,24个字节

;;╗⌠╝╜r⌠╜E╛=⌡░⌡M@Z⌠♂i⌡M╔

在线尝试!

说明:

;;╗⌠╝╜r⌠╜E╛=⌡░⌡M@Z⌠♂i⌡M╔
;;                        make two copies of input
  ╗                       save a copy to register 0
   ⌠╝╜r⌠╜E╛=⌡░⌡M          map over input:
    ╝                       save the element in register 1
     ╜r                     indices for input
       ⌠╜E╛=⌡░              filter:
        ╜E                    element in input at index
          ╛=                  equals element for outer map (from register 1)
                @Z        swap, zip input with map result
                  ⌠♂i⌡M   flatten each element in zipped list
                       ╔  uniquify

3

R,56个字节

function(x)lapply(unique(x),function(y)c(y,which(x==y)))

在线尝试!


这是我第一次尝试codegolf,欢迎任何反馈!


3
欢迎来到PPCG!不错的第一答案。
帕维尔

1
嘿,弗洛里安!很好的答案。这实际上是一个代码段,而不是程序或函数-假定输入被硬编码到中x,但是必须有一种读取输入的方法-通常我们使用scan或定义一个函数。此外,它必须输出,因此必须将其包装在a print或a中cat
朱塞佩

1
有关更多便捷的R高尔夫技巧,请参阅此问题:)
朱塞佩

1
多谢你们!并且指向r小技巧的链接肯定有用!
弗洛里安

2
只要您记得自己正在与其他R高尔夫球手打高尔夫球,@ Florian R并没有您想像的那么糟(除了弦挑战...)。如有任何疑问,请随时在聊天中ping我。有几个R高尔夫球手很活跃,他们肯定会提供建议,并感谢您的建议!欢迎打高尔夫球:)
朱塞佩


3

JavaScript(ES6),64字节

0索引

a=>a.map((v,i)=>a[-v]?a[-v].push(i):a[-v]=[v,i]).filter(x=>x[0])

注意,此假设输入数字为正,因此v> 0

略微修改测试(1索引)以匹配测试用例

var F=
a=>a.map((v,i)=>a[-v]?a[-v].push(i+1):a[-v]=[v,i+1]).filter(x=>x[0])

test = [ // output 1 indexed
  [3, 2, 2, 3],//    | [[3, 1, 4], [2, 2, 3]]
  [17], //           | [[17, 1]]
  [1, 1], //         | [[1, 1, 2]]
  [1, 1, 2], //      | [[1, 1, 2], [2, 3]]
  [1, 2, 3, 4], //   | [[1, 1], [2, 2], [3, 3], [4, 4]]
  [1, 1, 1, 1] //    | [[1, 1, 2, 3, 4]] 
]

test.forEach(t => {
  x = F(t)
  console.log(JSON.stringify(t)+ ' -> ' + JSON.stringify(x))
})


3

APL NARS,24个字节,12个字符

{∪⍵,¨⍸¨⍵=⊂⍵}

-4个字节感谢Adam测试:

  f←{∪⍵,¨⍸¨⍵=⊂⍵}

  ⎕fmt f 3 2 2 3
┌2────────────────┐
│┌3─────┐ ┌3─────┐│
││ 3 1 4│ │ 2 2 3││
│└~─────┘ └~─────┘2
└∊────────────────┘
  ⎕fmt f 17
┌1──────┐
│┌2────┐│
││ 17 1││
│└~────┘2
└∊──────┘
  ⎕fmt f 1 1
┌1───────┐
│┌3─────┐│
││ 1 1 2││
│└~─────┘2
└∊───────┘
  ⎕fmt f 1 2 3 4
┌4──────────────────────────┐
│┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐│
││ 1 1│ │ 2 2│ │ 3 3│ │ 4 4││
│└~───┘ └~───┘ └~───┘ └~───┘2
└∊──────────────────────────┘
  ⎕fmt f 1 1 1 1
┌1───────────┐
│┌5─────────┐│
││ 1 1 2 3 4││
│└~─────────┘2
└∊───────────┘

剃一个4个字节/ 2字符:{∪⍵,¨⍸¨⍵=⊂⍵}
亚当

3

SWI-Prolog165117字节

-48字节归功于Prolog高尔夫技巧

h(I):-I+[]-1.
[H|T]+R-N:-(select([H|A],R,[H|L],S),!,append(A,[N],L);append(R,[[H,N]],S)),O is N+1,(T+S-O,!;write(S)).

在线尝试!

说明

% The predicate that prints the grouped duplicates. It's a wrapper because we
% need some extra arguments to keep state:
enumerate_duplicates(Input) :- enumerate(Input, [], 1).

% In the golfed code, operators are used to represent this predicate.
% See /codegolf//a/153160
% Go through the input, build up the result on the way and print it.
enumerate([Head|Tail], Result, Index) :-
    (
        % If our current Result already contains a list that starts with the
        % current first element in our input, Head, NewIndexes will become the
        % new "tail" of that list in our next result list:
        select([Head|OldIndexes], Result, [Head|NewIndexes], NextResult),
        % Don't backtrack before this if goals below this fail:
        !,
        % The as-yet-unknown NewIndexes above should in fact be the same as
        % OldIndexes with our current Index appended:
        append(OldIndexes, [Index], NewIndexes)
    % Use ; instead of separate predicate rules.
    % See /codegolf//a/67032
    ;
        % If our current Result did not already contain Head, append a new list
        % for it with the current index:
        append(Result, [[Head, Index]], NextResult)
    ),
    % Increment our index counter:
    NextIndex is Index + 1,
    (
        % And continue with the rest of our input:
        enumerate(Tail, NextResult, NextIndex),
        % Don't backtrack if the above succeeded:
        !
    ;
        % If Tail is no longer a multi-element list, we're done. Print:
        write(NextResult)
    ).

3

K(oK),10个字节

解:

(!x),'.x:=

在线尝试!

例子:

(!x),'.x:=,17
,17 0
(!x),'.x:=1 1
,1 1 2
(!x),'.x:=1 0 1
(1 1 2
2 3)
(!x),'.x:=1 2 3 4
(1 0
2 1
3 2
4 3)

说明:

评估从右到左执行。我仍然认为这可以进一步打高尔夫球...

(!x),'.x:= / the solution
         = / group input into dictionary, item!indices
       x:  / save as variable x
      .    / value of x (the indices)
    ,'     / concatenate (,) each-both (') with
(  )       / do this together
 !x        / the key of x (i.e. the items)

笔记:

  • 14个字节而未声明x(,/)'+(!;.)@'=放弃了这种方法...

1
您可能会返回0索引结果,所以我认为您可以跳过1+
亚当


2

JavaScript(ES6),68个字节

0索引。

a=>a.map(p=(x,i)=>1/p[x]?b[p[x]].push(i):b.push([x,p[x]=i]),b=[])&&b

测试用例


输入数字为!= 0,这可能有助于避免1 / x欺骗
edc65

2

PHP 4.1,88字节

是的,很长。

假定使用默认 php.ini文件(short_open_tag = Onregister_globals = On)。

<?foreach($A as$k=>$v){!$b[$v]&&$b[$v]=array($v);$b[$v][]=$k;}print_r(array_values($b));

这以人类可读的方式展示了阵列。
可以通过键“ A”内的POST,GET和COOKIE传递值。


对于现代版本,可以使用(90个字节):

<?foreach($_GET[A]as$k=>$v){if(!$b[$v])$b[$v]=[$v];$b[$v][]=$k;}print_r(array_values($b));

结果是相同的,除了所有值必须通过键“ A”内的GET参数传递。


2

Perl 6的 63  61个字节

*.pairs.classify(*.value).map({.key,|.value».key}).sort(*.[1])

测试(从0开始)

{sort *.[1],map {.key,|.value».key},classify *.value,.pairs}

测试(基于0的相同算法)

展开:

# WhateverCode lambda (this is the parameter) 
*\                                            # [3,2,2,3]

# get a list of Pairs (zero based index => value)
.pairs                                        # (0=>3,1=>2,2=>2,3=>3)

# classify based on the values (unordered result)
.classify(*.value)                            # {2=>[1=>2,2=>2],3=>[0=>3,3=>3]}

# simplify the structure
.map({
  .key,         # the value
  |.value».key  # slip in the indexes
})                                            # ((3,0,3),(2,1,2))

# sort based on first index
.sort(*.[1])

2

Japt14个 9字节

0索引。

â £ð¶X iX

试试吧

â £ð¶X iX
â             :Deduplicate
  £           :Map each X
   ð          :  Get 0-based indices of elements in the input
    ¶X        :    That are equal to X
       iX     :  Prepend X

2

PHP 7.4+,71字节

* 73个字节来引用$_GET密钥,并避免显示警告。

片段:(演示

<?foreach($_GET[A]as$k=>$v){$b[$v][0]=$v;$b[$v][]=$k;}print_r([...$b]);

基于rep,我假设IsmaelMiguel知道在该社区中发布php代码的最佳方法,因此我是在他的基础上构建的。我不清楚是否<?要在我的代码段中包含/计算。由于这是我的处女作,我很高兴任何人都能解释一下是否有任何不必要的语法。ps:我还阅读了PHP高尔夫技巧,对我来说,这似乎是向Meta迁移的绝佳选择

对Ismael的代码段所做的改进包括:

  1. 无条件分配每个子数组中的第一个元素(值覆盖)
  2. Splatpacking而不是array_values()重新索引输出。


1

科特林,83个字节

{it.mapIndexed{i,c->c to i}.groupBy({(a,b)->a},{(a,b)->b}).map{(a,b)->listOf(a)+b}}

美化

{
    it.mapIndexed { i, c -> c to i }
        .groupBy({ (a, b) -> a }, { (a, b) -> b })
        .map { (a, b) -> listOf(a) + b }
}

测试

var f: (List<Int>) -> List<List<Int>> =
{it.mapIndexed{i,c->c to i}.groupBy({(a,b)->a},{(a,b)->b}).map{(a,b)->listOf(a)+b}}

data class Test(val input: List<Int>, val output: List<List<Int>>)

val tests = listOf(
        Test(listOf(3, 2, 2, 3), listOf(listOf(3, 0, 3), listOf(2, 1, 2))),
        Test(listOf(17), listOf(listOf(17, 0))),
        Test(listOf(1, 1), listOf(listOf(1, 0, 1))),
        Test(listOf(1, 1, 2), listOf(listOf(1, 0, 1), listOf(2, 2))),
        Test(listOf(1, 2, 3, 4), listOf(listOf(1, 0), listOf(2, 1), listOf(3, 2), listOf(4, 3))),
        Test(listOf(1, 1, 1, 1), listOf(listOf(1, 0, 1, 2, 3)))
)

fun main(args: Array<String>) {
    for (c in tests) {
        val o = f(c.input)
        if (o != c.output) {
            throw AssertionError("${c.input} -> $o != ${c.output}")
        }
    }
}

蒂奥

在线试用


该解决方案仅是片段,而不是完整的功能或程序。它要求变量i是预定义的。您可以通过将其转换为带有参数的lambda使其有效i
帕维尔

重新设计以解决@Pavel提出的问题
jrtapsell

1

斯威夫特4,107字节

... Yi。

{a in Dictionary(grouping:a.enumerated()){$0.1}.sorted{$0.1.first!.0<$1.1.first!.0}.map{[$0]+$1.flatMap{$0.0}}}

取消高尔夫:

let f = { (input: [Int]) -> [[Int]] in
    return Dictionary(grouping: input.enumerated(), by: { $0.element })
        .sorted { pairA, pairB in // Sort by order of first appearence (lowest offset)
            return pairA.value.first!.offset < pairB.value.first!.offset
        }.map { element, pairs in
            return [element] + pairs.map{ $0.offset /* +1 */} // add 1 here for 1 based indexing
        }
}

字典失去顺序太糟糕了,迫使我在重新排序时浪费了很多字符。这种滥用行为的隐闭参数(的$0$1...)和隐性元组成员(.0.1,...)是uhhhhh不漂亮。



1

红宝石54 52字节

->a{a.map{|i|[i]+(0..a.size).select{|j|a[j]==i}}|[]}

此版本允许nil(53字节):

->a{a.map{|i|[i]+(0...a.size).select{|j|a[j]==i}}|[]}

在线尝试!


挑战指定数组将仅包含正整数,并且将至少有一个元素。nil不是正整数。
帕维尔

@Pavel谢谢,我检查了一下但还是以某种方式错过了它
Asone Tuhid
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.