| Bytes | Lang | Time | Link |
|---|---|---|---|
| 272 | C# | 140210T222159Z | Hand-E-F |
| 108 | Ruby | 140208T033529Z | daniero |
| nan | 140208T002944Z | Adam Spe |
C#, 272 bytes
Not a great answer, but it works. If I understand Linq correctly, this opens the input file repeatedly, once for each line it writes to the output.
namespace System.Linq{
class P{
static void Main(string[]a)
{
var v=IO.File.ReadAllLines(a[0]).Select(y=>y.Split(',').ToList());
var l=v.First();
var s="\"\"";
for(;;){
IO.File.AppendAllText(a[1],string.Join(",",l)+"\n");
l=v.FirstOrDefault(x=>x[2]==s);
if(l==null)break;
s=l[0];
}
}
}
}
Input file:
"ID","Before","After","Value"
"1","3","5","Cat"
"2","5","","Apple"
"3","4","1","Dog"
"4","","3","Elephant"
"5","1","2","Banana"
Output file:
"ID","Before","After","Value"
"2","5","","Apple"
"5","1","2","Banana"
"1","3","5","Cat"
"3","4","1","Dog"
"4","","3","Elephant"
Ruby 109 108
Saved one whole character by using randomization instead of searching!
h,*t=[*$<]
t.shuffle!until t.each_cons(2).all?{|c|a,b=c.map{|y|y.lstrip.split /[,\s]+/}
a[1]==b[0]}
puts h,t
This only prints to stdout, so to save to a file use ruby csv.rb in.csv > out.csv.
$ cat test.csv
ID, Before, After, Value
1, 3, 5, Cat
2, 5, , Apple
3, 4, 1, Dog
4, , 3, Elephant
5, 1, 2, Banana
$ ruby csv.rb test.csv
ID, Before, After, Value
2, 5, , Apple
5, 1, 2, Banana
1, 3, 5, Cat
3, 4, 1, Dog
4, , 3, Elephant
Old version
puts gets,[*$<].permutation.find{|x|x.each_cons(2).all?{|c|a,b=c.map{|y|y.lstrip.split /[,\s]+/}
a[1]==b[0]}}
It simply finds the permutation of the lines where, for each line, the second column (Before) equals the first column (ID) of the next line.
VB.net (Non-Golfed)
Module Module3
Public Sub Main(ParamArray args() As String)
Dim items = CSVFileReader(args(0)).ToDictionary(Function(x) x(0))
Dim Current = items.First(Function(kvp) kvp.Value(2) = "").Value
Using out As New IO.StreamWriter(args(1), False) With {.AutoFlush=True }
Do
out.WriteLine("""{0}"",""{1}"",""{2}"",""{3}""", Current(0), Current(1), Current(2), Current(3))
If Current(1) <> "" Then Current = items(Current(1))
Loop Until Current(1) = ""
out.WriteLine("""{0}"",""{1}"",""{2}"",""{3}""", Current(0), Current(1), Current(2), Current(3))
End Using
End Sub
Public Iterator Function CSVFileReader(fn As String) As IEnumerable(Of String())
Using t As New FileIO.TextFieldParser(fn) With {.Delimiters ={","},.HasFieldsEnclosedInQuotes = True, .TextFieldType=FileIO.FieldType.Delimited }
While Not t.EndOfData
Yield t.ReadFields
End While
End Using
End Function
End Module
Probably a lot of room to golf that code.