Merging Home Letters (Golf Code)

The other day I wrote a merge code and although it works, I am disabled by the code. I would like to see how it will look in other languages.

So, for input, the routine accepts the contact list

Jim,Smith,2681 Eagle Peak,,Bellevue,Washington,United States,98004 Erica,Johnson,2681 Eagle Peak,,Bellevue,Washington,United States,98004 Abraham,Johnson,2681 Eagle Peak,,Bellevue,Washington,United States,98004 Marge,Simpson,6388 Lake City Way,,Burnaby,British Columbia,Canada,V5A 3A6 Larry,Lyon,52560 Free Street,,Toronto,Ontario,Canada,M4B 1V7 Ted,Simpson,6388 Lake City Way,,Burnaby,British Columbia,Canada,V5A 3A6 Raoul,Simpson,6388 Lake City Way,,Burnaby,British Columbia,Canada,V5A 3A6 

Then it combines the lines with the same address and last name into one record. Suppose the rows are not sorted). The code should also be flexible enough so that the fields can be set in any order (therefore, field indices will be required as parameters). For a family of two, it combines both name fields. For a family of three or more, the first name is set to "the" and the last to "last name".

 Erica and Abraham,Johnson,2681 Eagle Peak,,Bellevue,Washington,United States,98004 Larry,Lyon,52560 Free Street,,Toronto,Ontario,Canada,M4B 1V7 The,Simpson Family,6388 Lake City Way,,Burnaby,British Columbia,Canada,V5A 3A6 Jim,Smith,2681 Eagle Peak,,Bellevue,Washington,United States,98004 

My C # implementation:

 var source = File.ReadAllLines(@"sample.csv").Select(l => l.Split(',')); var merged = HouseholdMerge(source, 0, 1, new[] {1, 2, 3, 4, 5}); public static IEnumerable<string[]> HouseholdMerge(IEnumerable<string[]> data, int fnIndex, int lnIndex, int[] groupIndexes) { Func<string[], string> groupby = fields => String.Join("", fields.Where((f, i) => groupIndexes.Contains(i))); var groups = data.OrderBy(groupby).GroupBy(groupby); foreach (var group in groups) { string[] result = group.First().ToArray(); if (group.Count() == 2) { result[fnIndex] += " and " + group.ElementAt(1)[fnIndex]; } else if (group.Count() > 2) { result[fnIndex] = "The"; result[lnIndex] += " Family"; } yield return result; } } 

I don't like the way I needed to delegate the group. I would like C # to somehow convert the string expression to a delegate. eg Func groupby = f => "f [2] + f [3] + f [4] + f [5] + f [1];" I have a feeling that can probably be done in Lisp or Python. I look forward to a good implementation in other languages.

Edit: where is the wiki community checkbox checked? Some mod, please fix this.

+7
code-golf
source share
6 answers

Ruby - 181,155

The indices of the first / last name are in the code: a and b . The input is from ARGF.

 a,b=0,1 [*$<].map{|i|i.strip.split ?,}.group_by{|i|i.rotate(a).drop 1}.map{|i,j|k,l,m=j k[a]+=' and '+l[a]if l (k[a]='The';k[b]+=' Family')if m puts k*','} 
+3
source share

Python 2.6.6 - 287 Characters

It is assumed that you can hard-code the file name (with the name i ). If you want to enter input from the command line, it is about 16 characters.

 from itertools import* for z,g in groupby(sorted([l.split(',')for l in open('i').readlines()],key=lambda x:x[1:]), lambda x:x[2:]): l=list(g);r=len(l);k=','.join(z);o=l[0] if r>2:print'The,'+o[1],"Family,"+k, elif r>1:print o[0],"and",l[1][0]+","+o[1]+","+k, else:print','.join(o), 

Exit

 Erica and Abraham,Johnson,2681 Eagle Peak,,Bellevue,Washington,United States,98004 Larry,Lyon,52560 Free Street,,Toronto,Ontario,Canada,M4B 1V7 The,Simpson Family,6388 Lake City Way,,Burnaby,British Columbia,Canada,V5A 3A6 Jim,Smith,2681 Eagle Peak,,Bellevue,Washington,United States,98004 

I am sure that this can be improved, but it is late.

+1
source share

Python - 178 characters

 import sys d={} for x in sys.stdin:F,c,A=x.partition(',');d[A]=d.get(A,[])+[F] print"".join([" and ".join(v)+c+A,"The"+c+A.replace(c,' Family,',1)][2<len(v)]for A,v in d.items()) 

Exit

 Jim,Smith,2681 Eagle Peak,,Bellevue,Washington,United States,98004 The,Simpson Family,6388 Lake City Way,,Burnaby,British Columbia,Canada,V5A 3A6 Larry,Lyon,52560 Free Street,,Toronto,Ontario,Canada,M4B 1V7 Erica and Abraham,Johnson,2681 Eagle Peak,,Bellevue,Washington,United States,98004 
+1
source share

Python - not golf

I'm not sure what row order should be if the indices are not 0 and 1 for the input file

 import csv from collections import defaultdict class HouseHold(list): def __init__(self, fn_idx, ln_idx): self.fn_idx = fn_idx self.ln_idx = ln_idx def append(self, item): self.item = item list.append(self, item[self.fn_idx]) def get_value(self): fn_idx = self.fn_idx ln_idx = self.ln_idx item = self.item addr = [j for i,j in enumerate(item) if i not in (fn_idx, ln_idx)] if len(self) < 3: fn, ln = " and ".join(self), item[ln_idx] else: fn, ln = "The", item[ln_idx]+" Family" return [fn, ln] + addr def source(fname): with open(fname) as in_file: for item in csv.reader(in_file): yield item def household_merge(src, fn_idx, ln_idx, groupby): res = defaultdict(lambda:HouseHold(fn_idx, ln_idx)) for item in src: key = tuple(item[x] for x in groupby) res[key].append(item) return res.values() data = household_merge(source("sample.csv"), 0, 1, [1,2,3,4,5,6,7]) with open("result.csv", "w") as out_file: csv.writer(out_file).writerows(item.get_value() for item in data) 
+1
source share

Haskell - 341 321

(Changed according to comments).

Unfortunately, Haskell does not have a standard separation function that makes it quite long.

Log in to stdin, output to stdout.

 import List import Data.Ord main=interact$unlines.e.lines s[]=[] s(',':x)=sx sl@(x:y)=let(h,i)=break(==k)l in h:(si) t[]=[] tx=tail x h=head m=map k=',' el=m(t.(>>=(k:)))$(mc$groupBy g$sortBy(comparing t)$msl) c(x:[])=x c(x:y:[])=(h x++" and "++hy):tx cx="The":((h$t$hx)++" Family"):(t$t$hx) gab=ta==tb 
+1
source share

Lua, 434 bytes

 x,y=1,2 s,p,r,a=string.gsub,pairs,io.read,{}for j,b,c,d,e,f,g,h,i in r('*a'):gmatch('('..('([^,]*),'):rep(7)..'([^,]*))\n') do k=s(s(s(j,b,''),c,''),'[,%s]','')for l,m in p(a)do if not mf and (m[y]:match(c) and m[9]==k) then z=1 if md then m[x]="The"m[y]=m[y]..' family'm.f=1 else m[x]=m[x].." and "..b md=1 end end end if not z then a[#a+1]={b,c,d,e,f,g,h,i,k} end z=nil end for k,v in p(a)do v[9]=nil print(table.concat(v,','))end 
0
source share

All Articles