Make a numeric list converter

20

Don't you hate it when you want to copy-paste a list of numbers (vector, array ...), from one program to another, but the format you have the numbers on doesn't match the format you need it on?

For instance, in MATLAB you may have a space separated list like this:

[1 2 3 4 5]    (you can also have it comma separated, but that's not the point)

In Python you would need to insert commas to make that list a valid input, so you'd have to convert it to

[1, 2, 3, 4, 5]

to make it work. In C++ you might want something like:

{16,2,77,29}

and so on.

To simplify everyone's life, let's create a list converter, that takes a list on any format*, and outputs a list on another specified format.

The valid brackets are:

[list]
{list}
(list)
<list>
list      (no surrounding brackets)

The valid delimiters are:

a,b,c
a;b;c
a b c
a,  b,  c       <-- Several spaces. Must only be supported as input.
a;     b; c     <-- Several spaces. Must only be supported as input.
a   b   c       <-- Several spaces. Must only be supported as input. 

Note, the input can have any number of spaces between the numbers, but the output can choose to have zero spaces (if , or ; is used as delimiter), or a single space (if it's space-delimited).

In addition to the input list, there will be a string (or two characters) that defines the output format. The format string will first be the opening bracket type (only), [, (, <, { or (the last one is a single space used when there is no surrounding bracket). The bracket type will be followed by the delimiter type, ,, ; or (the last one is a single space). The two input format characters must be taken as a single argument (string or two consecutive characters) in the order described above.

Some examples of format strings:

[,    <-- Output format:   [a,b,c]
{;    <-- Output format:   {a;b;c}
      <-- Two spaces, output list has format:   a b c   

Rules:

  • The output can't have leading spaces
  • The output can have trailing spaces and a newline
    • The output should only be the list of numbers, not ans = or similar
  • The input will be a list of integer or decimal numbers (both positive and negative (and zero)), and a string of two characters
    • If the input consist of only integers, the output list should have only integers. If the input list consist of integers and decimal numbers, all output numbers can be decimal numbers. (It's optional to keep the integers as integers)
    • The maximum number of digits after the decimal point that must be supported are 3.
    • The input will be two arguments. I.e. the numbers are in one argument, and the format string is a single argument.
  • The code can be a program or function
  • The input can be function argument or STDIN

Some examples:

1 2 3 4
[,
[1,2,3,4]

<1;  2;  3>
 ;    <-- Space + semicolon
1;2;3
not valid:  1.000;2.000;3.000   (Input is only integers => Output must be integers)

{-1.3, 3.4, 4, 5.55555555}
[,
[-1.300,3.400,4.000,5.556]  (5.555 is also valid. Rounding is optional)
also valid: [-1.3,3.4,4,5.55555555]

The shortest code in bytes win. As always, the winner will be selected one week from the day the challenge was posted. Answers that are posted later can still win if they are shorter than the current winner.


Leaderboard

The Stack Snippet at the bottom of this post generates the catalog from the answers a) as a list of shortest solution per language and b) as an overall leaderboard.

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

## Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

## Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:

## Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the snippet:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes

var QUESTION_ID=66345,OVERRIDE_USER=44713;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

Stewie Griffin

Posted 2015-12-11T08:42:10.940

Reputation: 43 471

Is trailing and leading whitespace permitted? – overactor – 2015-12-11T09:44:39.093

@overactor, see the first two rules. Leading whitespace is not OK, trailing is OK. – Stewie Griffin – 2015-12-11T09:55:59.393

Can we take input in the opposite order? (delimiters first, list second) – Martin Ender – 2015-12-11T10:42:46.783

@MartinBüttner, yes. It's not specified that it has to be list first, so you may choose. – Stewie Griffin – 2015-12-11T11:02:58.950

J uses _ to denote negative elements. :( – Zgarb – 2015-12-11T18:27:42.667

Can the order of input arguments be chosen at will? – Luis Mendo – 2015-12-11T23:02:38.917

Answers

1

CJam, 27 bytes

l)l_5ms`-SerS%*\S-_o_'(#(f-

Try it here.

Explanation

l      e# Read the format string.
)      e# Extract the separator.
l_     e# Read the list.
5ms`   e# Get a string that contains -.0123456789.
-      e# Get the characters in the list that are not in the string.
Ser    e# Replace those characters with spaces.
S%     e# Split by those characters, with duplicates removed.
*      e# Join with the separator.
\S-    e# Remove spaces (if any) from the left bracket.
_o     e# Output a copy of that character before the stack.
_'(#   e# Find '( in the left bracket string.
(      e# Get -1 if '( is the first character, and -2 if it doesn't exist.
f-     e# Subtract the number from every character in the left bracket string,
          making a right bracket.

jimmy23013

Posted 2015-12-11T08:42:10.940

Reputation: 34 042

8

JavaScript (ES6), 75 82

As an anonymous function

Edit: 2 byte saved thx @user81655 (and 5 more just reviewing it)

(l,[a,b])=>a.trim()+l.match(/[-\d.]+/g).join(b)+']})> '['[{(< '.indexOf(a)]

Test snippet

F=(l,[a,b])=>a.trim()+l.match(/[-\d.]+/g).join(b)+']})> '['[{(< '.indexOf(a)]

// Test
console.log=x=>O.innerHTML+=x+'\n'
// default test suite
t=[['1 2 3 4','[,'],['<1;  2;  3>',' ;'],['{-1.3, 3.4, 4, 5.55555555}','[,']]
t.forEach(t=>console.log(t[0]+' *'+t[1]+'* '+F(t[0],t[1])))
function test() { console.log(P1.value+' *'+P2.value+'* '+F(P1.value,P2.value)) }
#P1 { width: 10em }
#P2 { width: 2em }
P1<input id=P1>
P2<input id=P2>
<button onclick="test()">-></button>
<pre id=O></pre>

edc65

Posted 2015-12-11T08:42:10.940

Reputation: 31 086

6

CJam, 35 34 bytes

l(S-l"{[<(,}]>);":BSerS%@*1$B5/~er

Test it here.

Expects the format on the first line and the list on the second.

Explanation

l   e# Read the format line.
(   e# Pull off the first character, which is the opening bracket.
S-  e# Set complement with a space, which leaves brackets unchanged and turns a space
    e# into an empty string.
l   e# Read the list.
"{[<(,}]>);":B
    e# Push this string which contains all the characters in the list we want to ignore.
Ser e# Replace each occurrence of one of them with a space.
S%  e# Split the string around runs of spaces, to get the numbers.
@   e# Pull up the the delimiter string.
*   e# Join the numbers in the list with that character.
1$  e# Copy the opening bracket (which may be an empty string).
B5/ e# Push B again and split it into chunks of 5: ["{[<(," "}]>);"]
~   e# Unwrap the array to leave both chunks on the stack.
er  e# Use them for transliteration, to turn the opening bracket into a closing one.

Martin Ender

Posted 2015-12-11T08:42:10.940

Reputation: 184 808

5

Pyth, 33 bytes

rjjezrXwJ"<>[]  {}(),;"d7@c6JChz6

Try it online: Demonstration or Test Suite

Explanation:

J"<>[]  {}(),;"  assign this string to J

rjjezrXwJd7@c6JChz6   implicit: z = first input string, e.g. "[;"
       w              read another string from input (the list of numbers)
      X Jd            replace every char of ^ that appears in J with a space
     r    7           parse ^ (the string of numbers and spaces) into a list
  jez                 put z[1] (the separator symbol) between the numbers
            c6J       split J into 6 pieces ["<>", "[]", "  ", "{}", "()", ",;"]
               Chz    ASCII-value of z[0] (opening bracket symbol)
           @          take the correspondent (mod 6) brackets from the list
 j                    and put the numbers between these brackets
r                 7   remove leading and trailing spaces

Jakube

Posted 2015-12-11T08:42:10.940

Reputation: 21 462

Can you add an explanation of how it works? – Shelvacu – 2015-12-12T18:37:56.437

1@Shel Here you are. – Jakube – 2015-12-12T18:58:36.383

5

PowerShell, 108 100 95 85 Bytes

$i,$z=$args;($z[0]+($i-split'[^\d.-]+'-ne''-join$z[1])+' }) >]'[($z[0]-32)%6]).Trim()

(see revision history for previous versions)

Golfed another 15 bytes by removing $b and $s variables and changing parens on the inner string.

This takes input as two strings and stores them into $i and $z, then we construct a new output string. The inner parens -splits $i with a regex to select only numeric digits, then -joins back together with the requested delimiter. We concatenate that with the first character of the delimiter input (e.g., [) and close it with indexing into a string based on the ASCII value of the first character and some formulation trickery. The outer .Trim() removes any leading or trailing spaces.

AdmBorkBork

Posted 2015-12-11T08:42:10.940

Reputation: 41 581

I think you could replace your closing bracket expression "]})>"["[{(< ".IndexOf($b[0])] with something like ' }) >]'[($b[0]-32)%6]. The ($b[0]-32)%6 gives you 0,2,4,5,1 for opening bracket characters, which you can use to index into the closing bracket string ' }) >]'. There might be a shorter "formula", but this seems good enough. – Danko Durbić – 2015-12-11T15:51:49.623

@DankoDurbić Excellent! I was trying to come up with some math to select on the correct output character based on ASCII values, but I couldn't find the right formula. I kept getting tripped up by () being right next to each other, but the other brackets have a character between, so I went with indexing. Thanks! – AdmBorkBork – 2015-12-11T16:02:52.367

Using String.Replace() instead of the -replace operator would buy you another 2 bytes (no need to escape or define a character class with []) – Mathias R. Jessen – 2015-12-12T23:28:32.327

@MathiasR.Jessen Unless I'm missing something here, the .Replace('[]{}()<>;,',' ') won't catch individual characters but instead try to match the symbolic whole, which doesn't exist. We'd need to use Regex.Replace, which involves a [regex]:: .NET call and would instead lengthen the code.

– AdmBorkBork – 2015-12-14T14:20:49.853

@TessellatingHeckler Thanks! I golfed another byte using -ne'' instead of |?{$_}. – AdmBorkBork – 2015-12-15T14:48:08.643

Neat, I didn't know you could -ne on an array. – TessellatingHeckler – 2015-12-15T16:33:28.220

4

Python 2, 96 bytes

import re
lambda(a,(b,c)):(b+c.join(re.findall('[-\d\.]+',a))+'])>} '['[(<{ '.index(b)]).strip()

Call as:

f(('{-1.3, 3.4, ,4, 5.55555555}','[,'))

Output:

[-1.3,3.4,4,5.55555555]

TFeld

Posted 2015-12-11T08:42:10.940

Reputation: 19 246

2

JavaScript (ES6), 82 92 116 92 bytes

(a,b)=>(c=a.match(/-?\d+(\.\d+)?/g).join(b[1]),d=b[0],d<"'"?c:d+c+"]}>)"["[{<(".indexOf(d)])

An anonymous function, run it like this

((a,b)=>(c=a.match(/-?\d+(\.\d+)?/g).join(b[1]),d=b[0],d<"'"?c:d+c+"]}>)"["[{<(".indexOf(d)]))("{1;  2;3;   4}","<;")

This can probably be golfed way further..

Ungolfed

(a,b)=>(                             // "{1;  2;3;   4}", "<;"
    c=a.match(/-?\d+(\.\d+)?/g)      // regex to match decimals
    .join(b[1]),                     // c -> "1;2;3;4"
    d=b[0],                          // d -> "<"
    d<"'" ?                          // if d is smaller than ' then ...
        c :                          // return just "1;2;3;4"
        d + c +                      // "<" + "1;2;3;4" + ...
        "]}>)" [ "[{<(".indexOf(d) ] // "]}>)"[2] -> ">"
)

Bassdrop Cumberwubwubwub

Posted 2015-12-11T08:42:10.940

Reputation: 5 707

I think you have to take a as a string, not a list. – overactor – 2015-12-11T09:23:12.577

Totally misunderstood this: The input will be a list of integer or decimal numbers (both positive and negative (and zero)), and a string of two characters. Fixed it, thanks – Bassdrop Cumberwubwubwub – 2015-12-11T09:48:33.410

2

Mathematica, 108 bytes

Mathematica is generally clumsy with string inputs unless the string is meant to be interpreted as a text.

c=Characters;t_~f~p_:=({b,s}=c@p;b<>Riffle[StringCases[t,NumberString],s]<>(b/.Thread[c@"[ {<(" -> c@"] }>)"]))

Explanation

StringCases[t,NumberString]returns the list of number strings.

Riffleinserts the separators between the numbers.

/.Thread[c@"[ {<(" -> c@"] }>)"]) replaces the left "bracket" with the right bracket.

<> is the infix form of StringJoin. It glues together the substrings.

DavidC

Posted 2015-12-11T08:42:10.940

Reputation: 24 524

2

Matlab, 85 bytes

@(s,x)[x(1) strjoin(regexp(s,'-?\d+\.?\d*','match'),x(2)) x(1)+(x(1)~=32)+(x(1)~=40)]

Example use:

>> @(s,x)[x(1) strjoin(regexp(s,'-?\d+\.?\d*','match'),x(2)) x(1)+(x(1)~=32)+(x(1)~=40)]
ans = 
    @(s,x)[x(1),strjoin(regexp(s,'-?\d+\.?\d*','match'),x(2)),x(1)+(x(1)~=32)+(x(1)~=40)]

>> ans('1 2.4 -3 -444.555 5', '[,')
ans =
[1,2.4,-3,-444.555,5]

Luis Mendo

Posted 2015-12-11T08:42:10.940

Reputation: 87 464

1

Bash + GNU Utilities, 90

b=${2:0:1}
echo $b`sed "s/[][{}()<>]//g;s/[,; ]\+/${2:1}/g"<<<"$1"``tr '[{(<' ']})>'<<<$b`

Digital Trauma

Posted 2015-12-11T08:42:10.940

Reputation: 64 644

1

Julia, 95 bytes

f(l,s)=(x=s[1]<33?"":s[1:1])*join(matchall(r"[\d.-]+",l),s[2])*string(x>""?s[1]+(s[1]<41?1:2):x)

This is a function f that accepts two strings and returns a string.

Ungolfed:

function f{T<:AbstractString}(l::T, s::T)
    # Extract the numbers from the input list
    n = matchall(r"[\d.-]+", l)

    # Join them back into a string separated by given separator
    j = join(n, s[2])

    # Set the opening bracket type as the empty string unless
    # the given bracket type is not a space
    x = s[1] < 33 ? "" : s[1:1]

    # Get the closing bracket type by adding 1 or 2 to the ASCII
    # value of the opening bracket unless it's an empty string
    c = string(x > "" ? s[1] + (s[1] < 41 ? 1 : 2) : x)

    # Put it all together and return
    return x * j * c
end

Alex A.

Posted 2015-12-11T08:42:10.940

Reputation: 23 761