0

[Python 3.x を使用] 2 つの列を持つ CSV ファイルを作成しようとしています。1 つは偽の電子メール アドレスを含み、2 番目の列にはそれぞれの関数で指定された特定の国コードを含める必要があります。

私は、国コードが - 少なくとも - 各電子メール アドレスに割り当てられて一様に配布されることを望みます。でも、一様に分散しない方法もあればいいのに。たとえば、ある国を電子メール アドレスの 30% に割り当て、別の国を 10% に割り当てることができます。

私の最大の苦労は、キーが電子メール アドレスで、値が国コードである辞書を作成し、長さが等しくなく、空の値 (None) を持たない 2 つのリストを圧縮することです。余談ですが、辞書を作成するのが最善の方法だと思いましたが、私はプログラミングとPythonに非常に慣れていないため、より良い解決策があれば共有してください!!

これは私のコードです:

from random import choice, randint
from string import ascii_lowercase
from itertools import zip_longest
import csv

def gen_name(length):
    """"Generates a random name with the given amount of characters."""
    return ''.join(choice(ascii_lowercase) for i in range(length))

def email_gen():
    """Generates a fake email address."""
    user = gen_name(randint(5, 10))
    host = gen_name(randint(5, 15))
    return user + "@" + host + ".com"

def gen_plain_email_list(n):
    """Generates a list of n amount of random e-mail addresses"""
    emaillist = []
    for i in range(n):
        emaillist.append(email_gen())
    return emaillist

def gen_email_dict(n):
    """Generates a dictionary where the key is an e-mail address and the value a random country code."""
    email_list = []
    cc = ['us', 'gb', 'de', 'fr', 'it', 'nl', 'es', 'ae', 'br', 'au']

    # Creating a list of n amount of e-mail addresses
    for i in range(n):
        email_list.append(email_gen())
    # Creates dictionary with with an e-mail address from email_list and
    # a random country code from the cc list
    email_dict = dict(zip_longest(email_list, cc, fillvalue=choice(cc)))
    return email_dict

def dict_to_csv(filename, n):
    with open(filename, 'w', newline='') as f:
        w = csv.writer(f)
        w.writerows(gen_email_dict(n).items())

dict_to_csv('test.csv', 1000)

助けてくれてありがとう!

4

3 に答える 3

0

確率の異なる国コードをランダムに選択するには、ランダムにコードを選択するユニバースを生成するために使用できる重みのセットを作成できます。ここでは Python 2 を使用していますが、一般的な考え方は同じです。

emails = [chr(65 + i) + '@foo.bar' for i in range(26)]

cc_weights = dict(
    us = 5,
    gb = 3,
    de = 2,
)

# A universe of country codes, based on the weighting we defined.
ccs = sum(([c] * n for c,n in cc_weights.iteritems()), [])

email_ccs = dict((e, choice(ccs)) for e in emails)
于 2013-06-02T13:39:13.687 に答える
0

国コードごとのパーセンテージがある場合は、十分な要素が得られるまで国リストを展開してから、リストをシャッフルします。

cc = [('us', .2), ('gb', .2), ('de', .1), ('fr', .05), ('it', .05)]
distribution = n / sum(dist for c, dist in cc)
countries = []
for c, dist in cc:
    countries.extend([c] * int(round(distribution * dist)))
# rounding errors may mean we have too few, add until we have enough
while len(countries) < n:
    countries.append(random.choice(cc)[0])
random.shuffle(countries)

これで、重みに従って国が均等に分散された状態で、これらを電子メール アドレスで圧縮できます。

于 2013-06-02T13:31:35.013 に答える
0

関数を悪用しようとしていzipます。あなたの場合、genexp または dict-comprehension を使用するのは簡単です:

def gen_email_dict(n):
    return {get_email(): choice(cc) for _ in range(n)}
    #return dict((get_email(), choice(cc)) for _ in range(n))  # python2

zip関数は同じ長さのシーケンスでのみ使用する必要がありますがzip_longest、同じ長さは許可されませんが、デフォルト値は任意の値を生成できる関数ではありません!

本当に を使用したい場合zip、これを行う方法は、無限の国コード ジェネレーターを使用することです。

cc = ['us', 'gb', 'de', 'fr', 'it', 'nl', 'es', 'ae', 'br', 'au']
def _countries():
    while True:
        yield choice(cc)

countries = _countries()

def gen_email_dict(n):
    # using zip_longest you'll get an infinite loop!!!
    return dict(zip((gen_email() for _ in range(n)), countries))
    # using itertools.islice you wont get an infinite loop.
    # but there is no reason to complicate things.
    #return dict(zip_longest((gen_email() for _ in range(n)), it.islice(countries, n)))
于 2013-06-02T13:22:41.997 に答える