2
\$\begingroup\$

Ok, so the input here is going to be a .csv file and so is the output. Now, given a .csv file/input like so

"apple","banana","apple,banana","orange"
"grape","orange","grape,orange","sprout"
# 0       1        2              3

strip out all commas for a given nth column's entries (index starts at 0). So, for the input above, the program would output a .csv file like so for n = 2:

"apple","banana","applebanana","orange"
"grape","orange","grapeorange","sprout"

If the particular column's entries do not have commas, then it does nothing. Could have any allowable/manageable number of columns, and if you somehow find that creating a program that takes more than one argument, say, a, b, c, ..., z like this

program(a=1,b=4,c=65, ..., z=0, mycsv.csv)

for respective columns 2, 5, and 66, which all strip out commas for each, to be shorter, then do that.


Shortest code measured in bytes wins, and it doesn't have to be a file that is output/input.

\$\endgroup\$
  • 2
    \$\begingroup\$ Are double quotes allowed in a field? If yes, how are they escaped? \$\endgroup\$ – Arnauld Sep 24 '16 at 21:26
  • 7
    \$\begingroup\$ This feels like a homework challenge under the guise of code-golf \$\endgroup\$ – Matt Sep 24 '16 at 22:55
  • \$\begingroup\$ How can we accept the file as input? string array? file name? whatever suits us? \$\endgroup\$ – Matt Sep 24 '16 at 22:56
  • \$\begingroup\$ Please clarify which characters can appear in the input fields. A test case that has commas outside the column we have to modify would also be helpful. \$\endgroup\$ – Dennis Sep 25 '16 at 15:25
  • \$\begingroup\$ Does it has to be zero based? E.g. If the language or approach is 1-based? \$\endgroup\$ – Christian Rondeau Sep 27 '16 at 21:00

10 Answers 10

3
\$\begingroup\$

05AB1E, 27 bytes

U|vy“","“©¡vyNXQi","-}})®ý,

Explanation

U                           # store index in X
 |v                         # for each line
   y“","“©¡                 # split on ","
           v          }     # for each in the split list
            yNXQi","-}      # if it's index equals X, remove any commas
                       )    # wrap in list
                        ®ý, # merge on "," and print

Try it online!

\$\endgroup\$
4
\$\begingroup\$

JavaScript (ES6), 95 93 90 bytes

Takes the content of the CSV file as its first parameter and the column index as its second parameter, with currying syntax.

let f =

s=>n=>s.split(/("[^"]*")/).map(c=>(c<' '?(k=0,c):k++-n*2?c:c.split`,`.join``),k=-1).join``

console.log(f(
`"apple","banana","apple,banana","orange"
"grape","orange","grape,orange","sprout"
`)(2));

\$\endgroup\$
  • 1
    \$\begingroup\$ The question says it must take a file as input. \$\endgroup\$ – DanTheMan Sep 24 '16 at 22:30
  • \$\begingroup\$ @DanTheMan - This is apparently not required anymore. \$\endgroup\$ – Arnauld Sep 25 '16 at 0:27
  • \$\begingroup\$ Are the s= and the parens in the regex necessary? \$\endgroup\$ – ETHproductions Sep 25 '16 at 0:46
  • \$\begingroup\$ @ETHproductions - My bad. The s= was left from a previous attempt. Thanks for noticing. I don't think I can get rid of the parens in the split, though. \$\endgroup\$ – Arnauld Sep 25 '16 at 0:49
  • \$\begingroup\$ Oh, I didn't realize that you could capture groups in the split argument! That's a cool feature. \$\endgroup\$ – ETHproductions Sep 25 '16 at 1:24
4
\$\begingroup\$

Ruby, 80 bytes

require'csv'
->n,x{CSV.read(x).map{|a|a[n].delete!',';a.to_csv(force_quotes:1)}}

A lambda that takes n and a file path argument, and returns a list of CSV rows.

\$\endgroup\$
  • \$\begingroup\$ Would .tr!?,,'' work? \$\endgroup\$ – m-chrzan Sep 25 '16 at 19:26
3
\$\begingroup\$

Python 2, 129 126 125 98 96 94 92 bytes

lambda n,f:''.join(c*((r[:i].count('"')-n*2)*','!=c)for r in open(f)for i,c in enumerate(r))

This is a lambda expression; to use it, prefix lambda with s=.

Iterates through each character of each line, filtering characters based on whether it's a comma and it's in a double-quoted string.

Now doesn't use the csv module at all!

Example run:

>>> s=lambda n,f:''.join(c*((r[:i].count('"')-n*2)*','!=c)for r in open(f)for i,c in enumerate(r))
>>> print s(2, 'test.csv')
"apple","banana","applebanana","orange"
"grape","orange","grapeorange","sprout"
\$\endgroup\$
2
\$\begingroup\$

Sh + GNU Sed GNU Sed, 36 28 + 1 bytes

Run with -r flag.

sed -r 's/(,?"\w*),?(\w*")/\1\2/'$1

One argument to select proper column (1-indexed). This uses a GNU-specific sed extension.


Old version: s/(,?\"\w*),?(\w*\")/\1\2/3

This required replacing the last 3 to select the proper column (1-indexed), which I'm not sure is allowed.

\$\endgroup\$
  • \$\begingroup\$ The question's test case is rather poor, but it says “strip out all commas for a given nth column's entries”, that sounds like each column may contain multiple commas. I'm afraid your solution is not handling them: pastebin.com/N3YrfMUN \$\endgroup\$ – manatwork Sep 26 '16 at 12:03
1
\$\begingroup\$

NodeJS, 129 bytes

(f,n)=>(require("fs").readFileSync(f)+"").split`
`.map(a=>a.match(/".*?"/g).map((b,i)=>i-n?b:b.replace(/,/g,"")).join`,`).join`
`

Defines an anonymous function that takes a file path and a number as input. It is no longer required to take input as a file, but I will leave this here for comparison.

\$\endgroup\$
1
\$\begingroup\$

Vim, 32 keystrokes (excluding column index)

This uses 1-based column indices (which might make this answer invalid).

The problem here is that Vim does not start from the current character but rather from the following one... So it's not "easy" to match the 1st set of quotes. Instead, it finds the closing quotes and selects backwards.

Solution

qq + the column index + /\v"(,"|$)<cr>vF":s/\%V,//<cr><cr>@qq@q

Explanation

  • qq starts recording macro q
  • /\v"(,"|$)<cr> searches for the next ending quote or end if line. Preceded by the input column number, it finds the nth occurrence
  • vF" visually selects the previous quote
  • ":s/\%V,//<cr> substitutes in the visual selection (\%V) every comma by nothing
  • <cr> goes to the next line
  • @qq@q makes the macro recursive, stops it and then play it until the end of the file.

Gotchas

  • If a column only contains commas, it will be detected as a column end and will break. This is a gray zone, I will adapt the answer is the question adds this to the test cases.
\$\endgroup\$
0
\$\begingroup\$

Haskell, 56 bytes

n!x=Math.FFT.Base.adjust(filter(/=','))n.read$'[':x++"]"

Without adjust you'd have to do something crazy like this:

n#(a,b)|a==n|filter(/=',')b|1<2=b; .. (n#)=<<zip ..
\$\endgroup\$
0
\$\begingroup\$

R, 59 bytes

 function(f,n){x=read.csv(f,h=0);x[,n]=gsub(",","",x[,n]);x}

A simple function that takes f, the location of the csv file, and n, the column number to replace. Reads in the file, removes all commas from the nth column, returns the resulting data frame. R indexes from 1, not from 0.

\$\endgroup\$
0
\$\begingroup\$

PHP, 81 bytes

while($r=fgetcsv(STDIN)){$r[$n=argv[1]]=strtr($r[$n],",","");fputcsv(STDOUT,$r);}

Run with php -r '<code>' <n> < <csvsource> > <csvtarget>.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.