Grouping Array Data

13

1

Given an integer matrix a and a nonnegative integer i, output a mapping b that maps the distinct values in the ith column of a to rows of a who have that value in the ith column.

You may assume that i is in the half-open range [0, num_cols(a)) (or [1, num_cols(a)] if you choose to use 1-based indices), and that all integers are within the representable range for your language. Input and output may be done in any reasonable manner, so long as it satisfies the basic requirements of the challenge (2D array -> mapping from ints to 2D arrays of ints). So long as the mapping is clear and consistent, the keys do not need to be included in the output.

Examples

[[1]], 0 -> {1: [[1]]}
[[3, 4, 5], [1, 4, 2], [5, 5, 5], [7, 7, 7], [1, 5, 9]], 1 -> {4: [[3, 4, 5], [1, 4, 2]], 5: [[5, 5, 5], [1, 5, 9]], 7: [[7, 7, 7]]}
[[1, 2, 3, 4, 5], [5, 4, 3, 2, 1], [2, 3, 4, 5, 6], [8, 9, 100, 0, 2]], 4 -> {5: [[1, 2, 3, 4, 5]], 1: [[5, 4, 3, 2, 1]], 6: [[2, 3, 4, 5, 6]], 2: [[8, 9, 100, 0, 2]]}

This is , so the shortest answer in bytes wins.

Mego

Posted 2018-05-20T03:29:15.963

Reputation: 32 998

1Sandbox – Mego – 2018-05-20T03:29:36.893

Just to check, can the mapping be a function? I'm not aware if this is a default, but it seems like something you intend to allow. – FryAmTheEggman – 2018-05-20T03:37:48.563

@FryAmTheEggman Yes, a function that meets our usual requirements is allowed. The I/O is extremely flexible. – Mego – 2018-05-20T03:42:51.570

3I like this I/O format very much because the output does not actually need to contain the input in itself. It's completely fine to return a function that accesses the input by reference as long as the function is a mapping. – JungHwan Min – 2018-05-20T04:40:17.033

@JungHwanMin I'm glad. I wanted to experiment with a very loose I/O format, and it's going well so far – Mego – 2018-05-20T04:44:20.520

Answers

4

Octave, 24 bytes

@(a,i)@(n)a(a(:,i)==n,:)

Try it online!

This creates an anonymous function that returns a matrix whose rows match the criteria. Octave indexes arrays at 1, not zero, and rows of a matrix are separated by a ;.

Matrices are what Octave does best—so well, in fact, that this challenge can be solved using pure syntax, no built-in functions.

Explanation

@(a,i)                   % creates an anonymous function that...
      @(n)               % returns another function that takes input n and
                         % maps it to the rows of a.
          a(         ,:) % Return all the columns of a, with the rows filtered by...
            a(:,i)       % whether the ith column of each row of a...
                  ==n    % equals n

NinjaBearMonkey

Posted 2018-05-20T03:29:15.963

Reputation: 9 925

3

Wolfram Language (Mathematica), 21 bytes

#~GroupBy~Extract@#2&

1-indexed. Returns an Association mapping.

Try it online!

This is a rare case in which a longer function (Extract) reduces the byte count (the shorter one being Part or [[ ... ]]) because Extract can curry. The result is this extremely concise two-function solution.

Explanation

Extract@#2

Function that extracts the <second input>th element.

#~GroupBy~ ...

Group the <first input> into lists associated with distinct keys <above function>[element].

JungHwan Min

Posted 2018-05-20T03:29:15.963

Reputation: 13 290

3

Haskell, 64 60 bytes

import Data.List
i!l=[(k,[a|a<-l,a!!i==k])|k<-nub$map(!!i)l]

Try it online!

Angs

Posted 2018-05-20T03:29:15.963

Reputation: 4 825

3

Ruby, 26 bytes

->a,i{a.group_by{|x|x[i]}}

Try it online!

Kirill L.

Posted 2018-05-20T03:29:15.963

Reputation: 6 693

2

Clean, 40 bytes

import StdEnv

\n l i=filter(\a=a!!n==i)l

Try it online!

A lambda (:: Int [[Int]] Int -> [[Int]]) where a partial application of just the first two arguments gives a mapping on the third argument.

Οurous

Posted 2018-05-20T03:29:15.963

Reputation: 7 916

2

J, 16 bytes

-3 bytes thanks to FrownyFrog!

{"1(~.@[;"0</.)]

Try it online!

Explanation:

A dyadic verb, taking i as its left argument and a as its right one.

] is the right argument, a

{"1 finds the numbers at ith column on each row

</. boxes groups from the right argument, selected by the keys, provided by the left one

~.@[ finds the unique keys

;"0 links the keys to the selected groups

Galen Ivanov

Posted 2018-05-20T03:29:15.963

Reputation: 13 815

;"0 instead of ,: saves 3 – FrownyFrog – 2018-05-20T09:22:31.163

@FrownyFrog Of course! I think I tried it, but apparently not the right way. – Galen Ivanov – 2018-05-20T11:18:07.183

2

jq, 100 bytes

uses an object for output, takes a command line argument $f plus an array on standard input

([.[]|.[$f]]|unique) as $c|[$c[] as $d|{($d|tostring):([.[]|[select(.[$f]==$d)]]|add)}]|add

deobfuscated:

.fieldnum as $field |
.input as $input |
([$input[] | .[$field]] | unique) as $categories |
[
    $categories[] as $category |
    {
        ($category | tostring) :
            ([$input[] | [select(.[$field]==$category)]] | add)
    }
] | add

abcq2

Posted 2018-05-20T03:29:15.963

Reputation: 21

Is this the language you're using?

– Οurous – 2018-05-21T23:20:08.737

2

R, 79 55 bytes

function(a,i)for(z in unique(a[,i]))print(a[a[,i]==z,])

Try it online!

24 bytes shaved off by @JayCe

ngm

Posted 2018-05-20T03:29:15.963

Reputation: 3 974

Save some bytes by extracting more directly. You can add a cat(z) before print to also print the key (I am unclear if this is required). – JayCe – 2018-05-22T19:48:18.420

1

Python 3, 45 bytes

lambda a,i:lambda n:[r for r in a if r[i]==n]

Try it online!

Returns the mapping represented as an anonymous lambda.

HyperNeutrino

Posted 2018-05-20T03:29:15.963

Reputation: 26 575

1

Proton, 29 bytes

a=>i=>n=>filter(r=>r[i]==n,a)

Try it online!

-3 bytes thanks to Mr. Xcoder using currying and filter (TBH I'm kind of surprised that filter actually worked)

HyperNeutrino

Posted 2018-05-20T03:29:15.963

Reputation: 26 575

Currying and using filter save you three bytes. – Mr. Xcoder – 2018-05-20T07:00:36.390

@Mr.Xcoder Cool, thanks :D – HyperNeutrino – 2018-05-20T15:13:56.967

0

JavaScript (Node.js), 29 bytes

a=>i=>n=>a.filter(e=>e[i]==n)

Try it online!

Updated now that I realize the loose output requirements. This uses currying as a golfing technique, and it also returns a function that takes an input n and maps that to the proper arrays.

NinjaBearMonkey

Posted 2018-05-20T03:29:15.963

Reputation: 9 925

0

Jelly, 5 bytes

ịⱮ⁹¹ƙ

Try it online!

Omits the keys, but should be clear.

Argument 1: i + 1
Argument 2: a

Erik the Outgolfer

Posted 2018-05-20T03:29:15.963

Reputation: 38 134

I don't think this would qualify as a mapping without the keys. – Dennis – 2018-05-22T03:32:45.517

@Dennis Hm, I had asked in the comments about it and OP said we can omit the keys (exactly what I edited into the question), and I had also linked this solution there (maybe shouldn't have flagged so early...). I did include the keys in a previous revision of this answer (waiting for an answer), so I'll just post another comment and let's see what OP says. – Erik the Outgolfer – 2018-05-22T09:01:01.353

0

Java 10, 135 64 bytes

m->i->n->new java.util.Stack(){{for(var a:m)if(a[i]==n)add(a);}}

Returns a Function<Integer, List<int[]>> accepting an integer-input n, which returns a List of arrays (matrix-rows) where the i'th values equal the given n.

Try it online.

Explanation:

m->i->               // Method with int-matrix and int parameters and Function return-type
  n->                //  Return a Function with integer as parameter
    new java.util.Stack(){{
                     //  and List of integer-arrays as return-type
      for(var a:m)   //   Loop over the arrays of the input-matrix
        if(a[i]==n)  //    If the `i`'the value of the current array equals `n`:
          add(a);}}  //     Add it to the return-List

Kevin Cruijssen

Posted 2018-05-20T03:29:15.963

Reputation: 67 575