Почтовое слияние (код гольф) - PullRequest
7 голосов
/ 07 ноября 2010

Я написал код слияния на днях, и, хотя он работает, я отключен кодом.Я хотел бы посмотреть, как это будет выглядеть на других языках.

Так что для ввода подпрограмма берет список контактов

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

Затем она объединит строки с тем же адресоми фамилия в одной записи.Предположим, строки не отсортированы).Код также должен быть достаточно гибким, чтобы поля можно было указывать в любом порядке (поэтому он должен принимать индексы полей в качестве параметров).Для семьи из двух человек это объединяет оба поля имени.Для семьи из трех или более имя устанавливается на «the», а фамилия на «фамилию family».

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

Моя реализация на C # это:

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;
    }            
}

Мне не нравится, как я должен был делать делегат groupby.Я хотел бы, чтобы у C # был какой-то способ преобразовать строковое выражение в делегат.например, Func groupby = f => "f [2] + f [3] + f [4] + f [5] + f [1];"У меня такое ощущение, что что-то подобное можно сделать в Lisp или Python.Я с нетерпением жду более приятной реализации на других языках.

Редактировать: Куда делся флажок вики сообщества?Некоторые моды, пожалуйста, исправьте это.

Ответы [ 6 ]

3 голосов
/ 07 ноября 2010

Рубин - 181 155

Индексы имени / фамилии в коде: a и bВходные данные из 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*','}
1 голос
/ 08 ноября 2010

Haskell - 341 321

(Изменения в соответствии с комментариями).

К сожалению, в Haskell нет стандартной функции разделения, которая делает это довольно длинным.

Вход в стандартный вывод, вывод в стандартный вывод.

import List
import Data.Ord
main=interact$unlines.e.lines
s[]=[]
s(',':x)=s x
s l@(x:y)=let(h,i)=break(==k)l in h:(s i)
t[]=[]
t x=tail x
h=head
m=map
k=','
e l=m(t.(>>=(k:)))$(m c$groupBy g$sortBy(comparing t)$m s l)
c(x:[])=x
c(x:y:[])=(h x++" and "++h y):t x
c x="The":((h$t$h x)++" Family"):(t$t$h x)
g a b=t a==t b
1 голос
/ 07 ноября 2010

Python - не в гольф

Я не уверен, каким должен быть порядок строк, если индексы не равны 0 и 1 для входного файла

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 голос
/ 07 ноября 2010

Python - 178 символов

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())

Выход

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 голос
/ 07 ноября 2010

Python 2.6.6 - 287 символов

Предполагается, что вы можете жестко закодировать имя файла (с именем i). Если вы хотите получить данные из командной строки, это увеличится на ~ 16 символов.

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),

Выход

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

Я уверен, что это можно улучшить, но уже поздно.

0 голосов
/ 21 ноября 2010

Lua, 434 байта

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 m.f and (m[y]:match(c) and m[9]==k) then z=1
if m.d then m[x]="The"m[y]=m[y]..' family'm.f=1 else m[x]=m[x].." and "..b m.d=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
...