Je voulais essayer quelque chose comme ça une fois
csv.py
qui rend la liste de type csv` bonnef.py
est suffisant.path
, mais c'est également appropriéf.py
def write(lines):
print 'write:', lines
csv.py
# -*- coding: utf-8 -*-
import f
def as_kvs(rows):
keys = rows[0]
value_rows = rows[1:]
return [dict(zip(keys, value_row)) for value_row in value_rows]
def write_first_one_or_empty(rows, sort_key, filter_key, filter_value, write_key):
#Faire plusieurs kv
kvs = as_kvs(rows)
#Trier par clé spécifiée
_sorted = sorted(kvs, key=lambda row: row[sort_key])
#Filtre uniquement là où la clé spécifiée a la valeur spécifiée
_filtered = filter(lambda row: row[filter_key] == filter_value, _sorted)
if 0 < len(_filtered):
#Extraire la première ligne avec la clé spécifiée
_mapped_one = map(lambda row: row[write_key], _filtered)[0]
#Écrire
f.write([_mapped_one])
else:
#Créer un fichier vide
f.write([])
def write_all_or_empty(rows, filter_key, filter_value, write_key):
#Faire plusieurs kv
kvs = as_kvs(rows)
#Filtre uniquement là où la clé spécifiée a la valeur spécifiée
_filtered = filter(lambda row: row[filter_key] == filter_value, kvs)
if _filtered:
#Extraire toutes les lignes avec la clé spécifiée
_mapped = map(lambda row: row[write_key], _filtered)
#Écrire
f.write(_mapped)
else:
#Créer un fichier vide
f.write([])
def write_all_or_error(rows, filter_key, filter_value, write_key):
#Faire plusieurs kv
kvs = as_kvs(rows)
#Filtre uniquement là où la clé spécifiée a la valeur spécifiée
_filtered = filter(lambda row: row[filter_key] == filter_value, kvs)
if _filtered:
#Extraire toutes les lignes avec la clé spécifiée
_mapped = map(lambda row: row[write_key], _filtered)
#Écrire
f.write(_mapped)
else:
#Erreur
raise Exception("no result")
main.py
# status,Étant donné un csv composé de code
#Trier par code
#Le premier cas où le statut est actif
#Écrire le code
#Sinon, créez simplement un fichier
csv.write_first_one_or_empty(
[['status', 'code'], ['dead', '001'], ['active', '003'], ['active', '002']],
'code', 'status', 'active', 'code'
)
#résultat
# write: ['002']
main.py
# name,Étant donné un csv composé de genre
#Tous les cas où le sexe est masculin
#Écrivez le nom
#Sinon, créez simplement un fichier
csv.write_all_or_empty(
[['name', 'gender'], ['Eva', 'female'], ['Sunny', 'female']],
'gender', 'male', 'name'
)
#résultat
# write: []
main.py
# status,Donner csv composé de tel
#Tous les cas où le statut est mort
#Exporter tel
#Sinon une erreur
csv.write_all_or_error(
[['status', 'tel'], ['dead', '090-1111-1111'], ['active', '090-9999-9999']],
'status', 'dead', 'tel'
)
#résultat
# write: ['090-1111-1111']
def write_first_one_or_empty(rows, sort_key, filter_key, filter_value, write_key):
- #Faire plusieurs kv
+ # as kvs
kvs = as_kvs(rows)
- #Trier par clé spécifiée
+ # sort by specified key
_sorted = sorted(kvs, key=lambda row: row[sort_key])
- #Filtre uniquement là où la clé spécifiée a la valeur spécifiée
+ # filter by specified key and value
_filtered = filter(lambda row: row[filter_key] == filter_value, _sorted)
if 0 < len(_filtered):
- #Extraire la première ligne avec la clé spécifiée
+ # extract by specified key and first one
_mapped_one = map(lambda row: row[write_key], _filtered)[0]
- #Écrire
+ # write
f.write([_mapped_one])
else:
- #Créer un fichier vide
+ # write empty
f.write([])
def write_all_or_empty(rows, filter_key, filter_value, write_key):
- #Faire plusieurs kv
+ # as kvs
kvs = as_kvs(rows)
- #Filtre uniquement là où la clé spécifiée a la valeur spécifiée
+ # filter by specified key and value
_filtered = filter(lambda row: row[filter_key] == filter_value, kvs)
if _filtered:
- #Extraire toutes les lignes avec la clé spécifiée
+ # extract by specified key
_mapped = map(lambda row: row[write_key], _filtered)
- #Écrire
+ # write
f.write(_mapped)
else:
- #Créer un fichier vide
+ # write empty
f.write([])
def write_all_or_error(rows, filter_key, filter_value, write_key):
- #Faire plusieurs kv
+ # as kvs
kvs = as_kvs(rows)
- #Filtre uniquement là où la clé spécifiée a la valeur spécifiée
+ # filter by specified key and value
_filtered = filter(lambda row: row[filter_key] == filter_value, kvs)
if _filtered:
- #Extraire toutes les lignes avec la clé spécifiée
+ # extract by specified key
_mapped = map(lambda row: row[write_key], _filtered)
- #Écrire
+ # write
f.write(_mapped)
else:
- #Erreur
+ # error
raise Exception("no result")
# as kvs
et # write
.La méthode qui a été découpée est comme ça
+def sort_by_specified_key(kvs, key):
+ return sorted(kvs, key=lambda row: row[key])
+def filter_by_specified_key_and_value(kvs, key, value):
+ return filter(lambda row: row[key] == value, kvs)
+def extract_by_specified_key_and_first_one(kvs, key):
+ return kvs[0][key]
+def extract_by_specified_key(kvs, key):
+ return map(lambda row: row[key], kvs)
+def error():
+ raise Exception("no result")
Le corps principal est comme ça
-def write_first_one_or_empty(rows, sort_key, filter_key, filter_value, write_key):
+def write_first_one_or_empty(rows, sort_key, filter_key, filter_value, extraction_key):
- # as kvs
kvs = as_kvs(rows)
- # sort by specified key
- _sorted = sorted(kvs, key=lambda row: row[sort_key])
+ _sorted = sort_by_specified_key(kvs, sort_key)
- # filter by specified key and value
- _filtered = filter(lambda row: row[filter_key] == filter_value, _sorted)
+ _filtered = filter_by_specified_key_and_value(_sorted, filter_key, filter_value)
if 0 < len(_filtered):
- # extract by specified key and first one
- _mapped_one = map(lambda row: row[write_key], _filtered)[0]
- # write
- f.write([_mapped_one])
+ extracted_one = extract_by_specified_key_and_first_one(_filtered, extraction_key)
+ f.write([extracted_one])
else:
- # write empty
f.write([])
-def write_all_or_empty(rows, filter_key, filter_value, write_key):
+def write_all_or_empty(rows, filter_key, filter_value, extraction_key):
- # as kvs
kvs = as_kvs(rows)
- # filter by specified key and value
- _filtered = filter(lambda row: row[filter_key] == filter_value, kvs)
+ _filtered = filter_by_specified_key_and_value(kvs, filter_key, filter_value)
if _filtered:
- # extract by specified key
- _mapped = map(lambda row: row[write_key], _filtered)
- # write
- f.write(_mapped)
+ extracted = extract_by_specified_key(_filtered, extraction_key)
+ f.write(extracted)
else:
- # write empty
f.write([])
-def write_all_or_error(rows, filter_key, filter_value, write_key):
+def write_all_or_error(rows, filter_key, filter_value, extraction_key):
- # as kvs
kvs = as_kvs(rows)
- # filter by specified key and value
- _filtered = filter(lambda row: row[filter_key] == filter_value, kvs)
+ _filtered = filter_by_specified_key_and_value(kvs, filter_key, filter_value)
if _filtered:
- # extract by specified key
- _mapped = map(lambda row: row[write_key], _filtered)
- # write
- f.write(_mapped)
+ extracted = extract_by_specified_key(_filtered, extraction_key)
+ f.write(extracted)
else:
- # error
- raise Exception("no result")
+ error()
==
que pour filter_key
et filter_value
, donc vous ne pouvez pas filtrer comme ʻage <20`J'ai préparé head
et tail
car l'accès à l'index est un peu hostile.
+def head(xs):
+ return xs[0]
+def tail(xs):
+ return xs[1:]
Où utiliser
def as_kvs(rows):
- keys = rows[0]
- value_rows = rows[1:]
+ keys = head(rows)
+ value_rows = tail(rows)
def extract_by_specified_key_and_first_one(kvs, key):
- return kvs[0][key]
+ return head(kvs)[key]
Changement de filter_by_specified_key_and_value
pour recevoir predicate
au lieu de key, value
pour être un peu plus flexible
-def filter_by_specified_key_and_value(kvs, key, value):
- return filter(lambda row: row[key] == value, kvs)
+def filter_by_predicate(kvs, predicate):
+ return filter(predicate, kvs)
Ensuite, filter_by_predicate
ne fait rien de plus que filter
et le rejette.
-def filter_by_predicate(kvs, predicate):
- return filter(predicate, kvs)
Ensuite, j'ai créé head
, donc je n'aurais peut-être pas à préparer ʻextract_by_specified_key_and_first_one`.
Si les noms des méthodes divisées en petites parties sont corrects, il est difficile que le traitement ne devienne pas clair même s'ils sont utilisés en combinaison.
-def extract_by_specified_key_and_first_one(kvs, key):
- return head(kvs)[key]
Voici le corps principal qui reflète ce qui précède
-def write_first_one_or_empty(rows, sort_key, filter_key, filter_value, extraction_key):
+def write_first_one_or_empty(rows, sort_key, predicate, extraction_key):
kvs = as_kvs(rows)
_sorted = sort_by_specified_key(kvs, sort_key)
- _filtered = filter_by_specified_key_and_value(_sorted, filter_key, filter_value)
+ _filtered = filter(predicate, _sorted)
if 0 < len(_filtered):
- extracted_one = extract_by_specified_key_and_first_one(_filtered, extraction_key)
+ extracted_one = head(_filtered)[extraction_key]
f.write([extracted_one])
else:
f.write([])
-def write_all_or_empty(rows, filter_key, filter_value, extraction_key):
+def write_all_or_empty(rows, predicate, extraction_key):
kvs = as_kvs(rows)
- _filtered = filter_by_specified_key_and_value(kvs, filter_key, filter_value)
+ _filtered = filter(predicate, kvs)
if _filtered:
extracted = extract_by_specified_key(_filtered, extraction_key)
f.write(extracted)
else:
f.write([])
-def write_all_or_error(rows, filter_key, filter_value, extraction_key):
+def write_all_or_error(rows, predicate, extraction_key):
kvs = as_kvs(rows)
- _filtered = filter_by_specified_key_and_value(kvs, filter_key, filter_value)
+ _filtered = filter(predicate, kvs)
if _filtered:
extracted = extract_by_specified_key(_filtered, extraction_key)
f.write(extracted)
else:
error()
filter
à f.write
dans les deux derniers des trois méthodes principales du corps est exactement le même, alors supprimez-le.+def filter_and_extract_and_write_if_not_empty(kvs, predicate, extraction_key):
+ _filtered = filter(predicate, kvs)
+
+ if _filtered:
+ extracted = extract_by_specified_key(_filtered, extraction_key)
+ f.write(extracted)
Depuis qu'il a été coupé, le nombre de lignes dans le corps principal a diminué
def write_all_or_empty(rows, predicate, extraction_key):
kvs = as_kvs(rows)
- _filtered = filter(predicate, kvs)
+ filter_and_extract_and_write_if_not_empty(kvs, predicate, extraction_key)
- if _filtered:
- extracted = extract_by_specified_key(_filtered, extraction_key)
- f.write(extracted)
- else:
+ if not kvs:
f.write([])
def write_all_or_error(rows, predicate, extraction_key):
kvs = as_kvs(rows)
- _filtered = filter(predicate, kvs)
+ filter_and_extract_and_write_if_not_empty(kvs, predicate, extraction_key)
- if _filtered:
- extracted = extract_by_specified_key(_filtered, extraction_key)
- f.write(extracted)
- else:
+ if not kvs:
error()
filter_and_extract_and_write_if_not_empty
a été découpée, donc la partie ʻelse
est restée du côté du corps principal.La mauvaise politique mentionnée ci-dessus est réduite et refaite
Faites attention à la deuxième méthode corporelle
Cette fois, il n'est pas nécessaire de séparer explicitement le traitement pour le cas avec le contenu de la liste et le cas avec la liste vide Fondamentalement, si le traitement auquel la liste est passée est le même, il n'est pas nécessaire de connaître la longueur de la liste (cela ne devrait pas être)
Il vaut mieux passer ceci à f.write
sans savoir s'il s'agit d'un contenu ou d'une liste vide
def write_all_or_empty(rows, predicate, extraction_key):
kvs = as_kvs(rows)
_filtered = filter(predicate, kvs)
- if _filtered:
- extracted = extract_by_specified_key(_filtered, extraction_key)
- f.write(extracted)
- else:
- f.write([])
+ extracted = extract_by_specified_key(_filtered, extraction_key)
+ f.write(extracted)
Ensuite, faites attention à la première méthode corporelle.
S'il ne s'agit pas d'une liste vide, le premier élément est retiré, traité et de nouveau répertorié.
cette
Le flux
map
Je changerai l'idée en flux
Tout d'abord, préparez une méthode pour obtenir le premier élément correspondant de la liste avec une longueur maximale de 1.
+def find_first(kvs, predicate):
+ for kv in kvs:
+ if predicate(kv):
+ return [kv]
+ else:
+ return []
Ensuite, vous n'avez pas à vous soucier du contenu comme le deuxième de la méthode du corps principal.
De plus, comme il s'agit d'une conversion de liste, vous pouvez utiliser ʻextract_by_specified_key au lieu de
headet d'un accès
key`.
def write_first_one_or_empty(rows, sort_key, predicate, extraction_key):
kvs = as_kvs(rows)
_sorted = sort_by_specified_key(kvs, sort_key)
+ first = find_first(_sorted, predicate)
- _filtered = filter(predicate, _sorted)
-
- if 0 < len(_filtered):
- extracted_one = head(extract_by_specified_key(_filtered, extraction_key))
- f.write([extracted_one])
- else:
- f.write([])
+ extracted = extract_by_specified_key(first, extraction_key)
+ f.write(extracted)
La clause ʻif et la clause ʻelse
des méthodes du corps principal 1 et 2 s'inscrivent dans la granularité du "processus d'écriture sans tenir compte de la longueur de la liste"
Dans un mauvais exemple, ʻif et ʻelse
étaient un groupe de processus d'exportation, mais c'était une mauvaise idée de ne supprimer que ʻif`.
csv
, mais il y a juste un processus d'opération de listeHead
et tail
seront probablement utilisés dans d'autres modules à l'avenir, donc public
l.py
et éliminez-le de csv.py
list.py
était bien, mais le nom entre en conflit avec le standard list ()
, donc je l'ai décalé de manière appropriée)l.py
+# -*- coding: utf-8 -*-
+
+
+def head(xs):
+ return xs[0]
+
+
+def tail(xs):
+ return xs[1:]
+
+
+def find_first(xs, predicate):
+ for x in xs:
+ if predicate(x):
+ return [x]
+ else:
+ return []
kvs
pour trier et extraire, ce qui n'est qu'une opération de dictionnaire, donc créez d.py
et expulsez-le de csv.py
.kvs
en un nom abstrait approprié.d.py
+# -*- coding: utf-8 -*-
+
+
+def extract_by_specified_key(xs, key):
+ return map(lambda x: x[key], xs)
+
+
+def sort_by_specified_key(xs, key):
+ return sorted(xs, key=lambda x: x[key])
csv.py
, alors rendez-le privé
-def as_kvs(rows):
+def __as_kvs(rows):
-def error():
+def __error():
kvs
est juste une structure de données temporaire préparée en convertissant la structure de données attendue par csv.py
uniquement pour faciliter le traitement en interne.
kvs
est en fait dict
, mais le type dict
n'apparaît pas dans les arguments publiés ou la valeur de retour de csv.py
.
En d'autres termes, le type dict
n'existe nulle part en tant que fonction fournie par le module, il ne doit donc pas être exposé.
De plus, le type d'argument de ʻas_kvs est
list, mais en raison de restrictions telles que la configuration de
header + [body]et du fait que toutes les colonnes correspondent,
l.py et
J'ai pensé qu'il était préférable de faire du traitement privé csv.py
plutôt que d.py`
private
est utiliséeprivée
qui n'est utilisée qu'une seule fois (cela peut être pour et contre)Quand il s'agit de modules légèrement plus grands, il peut être extrêmement difficile de savoir où et combien de modules privés sont utilisés.
Si vous le faites, il peut être difficile de refactoriser la méthode «privée» ou de comprendre la gamme d'influence, ce qui peut être assez difficile.
public 1 -> private 1 -> private 2 -> private 3
public a -> private a -> private b
public x -> private x
Il est beaucoup plus facile de saisir le tableau d'ensemble si vous pensez qu'il y a en fait trois «public». Vous pouvez refactoriser «privé» en toute tranquillité.
public 1 -> private 1
|
V
public a -> private a -> private b
^
|
public x -> private x -> private y
«private 1» et «private x» peuvent être modifiés dans une certaine mesure facilement, mais si vous corrigez légèrement «private b», cela affectera tout «public».
Essayez de définir private
dans la méthode qui n'est utilisée qu'à partir d'un seul endroit
C'est la méthode que j'ai essayée sans permission quand j'étais là-bas, mais il n'y a pas d'exposition ou de discussion proprement dite, mais je pense que c'est une bonne idée et je l'utilise beaucoup dans les cordons jetables et les projets solo
Puisque __error
n'est utilisé qu'à un seul endroit, je l'ai préparé avec def
dans def
Au fait, j'ai supprimé l'ennuyeux __
parce qu'il devenait de toute façon invisible de l'extérieur.
def write_all_or_error(rows, predicate, extraction_key):
+ def write_or_error(kvs):
+ if kvs:
+ f.write(kvs)
+ else:
+ raise Exception("no result")
+
kvs = __as_kvs(rows)
_filtered = filter(predicate, kvs)
extracted = d.extract_by_specified_key(_filtered, extraction_key)
- if extracted:
- f.write(extracted)
- else:
- __error()
+ write_or_error(extracted)
Bien sûr, __as_kvs
est utilisé à de nombreux endroits, alors ne le changez pas.
La responsabilité du module se limite donc à la "conversion" et le test est mis en œuvre.
Il est décidé de finir par «return» sans «sortie»
Parallèlement à cela, le nom de la méthode a été changé de write_
à ʻextract_`.
-def write_first_one_or_empty(rows, sort_key, predicate, extraction_key):
+def extract_first_one_or_empty(rows, sort_key, predicate, extraction_key):
kvs = __as_kvs(rows)
_sorted = d.sort_by_specified_key(kvs, sort_key)
first = l.find_first(_sorted, predicate)
- extracted = d.extract_by_specified_key(first, extraction_key)
- f.write(extracted)
+ return d.extract_by_specified_key(first, extraction_key)
-def write_all_or_empty(rows, predicate, extraction_key):
+def extract_all_or_empty(rows, predicate, extraction_key):
kvs = __as_kvs(rows)
_filtered = filter(predicate, kvs)
- extracted = d.extract_by_specified_key(_filtered, extraction_key)
- f.write(extracted)
+ return d.extract_by_specified_key(_filtered, extraction_key)
-def write_all_or_error(rows, predicate, extraction_key):
- def write_or_error(kvs):
- if kvs:
- f.write(kvs)
+def extract_all_or_error(rows, predicate, extraction_key):
+ def it_or_error(xs):
+ if xs:
+ return xs
else:
raise Exception("no result")
kvs = __as_kvs(rows)
_filtered = filter(predicate, kvs)
extracted = d.extract_by_specified_key(_filtered, extraction_key)
- write_or_error(extracted)
+ return it_or_error(extracted)
En conséquence, ʻimport disparaît, il peut donc être confirmé que
csv.py` ne traite plus file-io.
-from private import f
Le test ressemble à ceci
csv_test.py
# -*- coding: utf-8 -*-
import csv
assert csv.extract_first_one_or_empty(
[['status', 'code'], ['dead', '001'], ['active', '003'], ['active', '002']],
'code', lambda kvs: kvs['status'] == 'active', 'code'
) == ['002']
assert csv.extract_first_one_or_empty(
[['status', 'code'], ['dead', '001']],
'code', lambda kvs: kvs['status'] == 'active', 'code'
) == []
csv.py
# -*- coding: utf-8 -*-
import l
import d
def __as_kvs(rows):
keys = l.head(rows)
value_rows = l.tail(rows)
return [dict(zip(keys, value_row)) for value_row in value_rows]
def extract_first_one_or_empty(rows, sort_key, predicate, extraction_key):
kvs = __as_kvs(rows)
_sorted = d.sort_by_specified_key(kvs, sort_key)
first = l.find_first(_sorted, predicate)
return d.extract_by_specified_key(first, extraction_key)
def extract_all_or_empty(rows, predicate, extraction_key):
kvs = __as_kvs(rows)
_filtered = filter(predicate, kvs)
return d.extract_by_specified_key(_filtered, extraction_key)
def extract_all_or_error(rows, predicate, extraction_key):
def it_or_error(xs):
if xs:
return xs
else:
raise Exception("no result")
kvs = __as_kvs(rows)
_filtered = filter(predicate, kvs)
extracted = d.extract_by_specified_key(_filtered, extraction_key)
return it_or_error(extracted)
ou
for`, et tout ce que vous avez à faire est d'appeler la méthode.def
interne, sautez-le et lisez-le depuis le début du texte)l.py
et d.py
qui semblent être utiles dans le futur sont nésJe ne peux pas le dire en un mot ...
return result #return result
, ce qui est inattendu# Ce processus concerne les ~ ~ spécifications
, etc.# ~ ~ a été pris en considération et implémenté comme ça
, etc.privé
au lieu de commenter et nommez-le correctement comme dans cet exemple.private
privée
private
à la fin devrait avoir un nom simple et une chose à fairelen ()
ou head ()
ou .split ()
head ()
un par unpublics
plus tard.public
filter
est réglé sur find_first
et où il était filter
jusqu'à la fin fait partie de ʻif write else vide
et ʻif write else error`def
in def
private
créée en convertissant un commentaire en méthode est appelée à partir d'un seul endroitscala peut être obéissant
def upperJoin(xs: List[String], sep: String): String = {
def upper(xs: List[String]): List[String] = xs.map(_.toUpperCase)
def join(xs: List[String]): String = xs.mkString(sep)
join(upper(xs))
}
upperJoin(List("hello", "world"), " ") // HELLO WORLD
Même avec java, il est possible d'utiliser Function <T, R>
etc.
public static String upperJoin(List<String> xs, String sep) {
Function<List<String>, List<String>> upper = _xs -> _xs.stream().map(String::toUpperCase).collect(toList());
Function<List<String>, String> join = _xs -> _xs.stream().collect(joining(sep));
return join.apply(upper.apply(xs));
}
upperJoin(asList("hello", "world"), " "); // HELLO WORLD
haskell peut aussi être Ou plutôt, l'idée vient du sens de définir une fonction haskell par valeur.
upperJoin xs sep = (join . upper) xs
where
upper = map (map toUpper)
join = intercalate sep
upperJoin ["hello", "world"] " " -- HELLO WORLD
Ainsi, l'exemple java est proche de haskell, et vous pouvez l'écrire en python comme ceci:
(Dans PEP 8, c'est une violation de la norme de codage de nommer et de lier lambda
, mais je déteste l'imbrication, donc il y a plus de gens ici si je suis seul)
def upper_join(xs, sep):
upper = lambda xs: [x.upper() for x in xs]
join = lambda xs: sep.join(xs)
return join(upper(xs))
upper_join(['hello', 'world'], ' ') # HELLO WORLD
kvs
était la liste
de dict
, donc c'était un peu différent de le mettre facilement dans d.py
...Je voulais juste l'essayer, donc j'étais satisfait
Cela n'a pas d'importance, mais quand je vois les lettres noires sur les zones rouges et vertes, je pense toujours que cela ressemble à une pastèque.
Recommended Posts