繁体   English   中英

通过组合名字和姓氏数组中的值来创建唯一的名称

[英]Create a unique name by combining the values in the first and last names array

我有两个数组,我想通过组合这两个数组来创建一个名称。 但是,不应重复。

除了查找名称结果值数组的递归方式之外,我是否还可以返回随机名称,就好像它是随机的一样?

最简单的方法是将随机生成的名称存储在列表中,并在每次创建新名称(如下所示)时查找列表。

import random
first_name = ['tony', 'adam', 'agustin', 'branden','stan']
last_name = ['smith', 'stark',  'wlliams']

full_name_dup_list = []

def generate_full_name():
    full_name =random.choice(first_name) +" "+ random.choice(last_name)
    if full_name in full_name_dup_list:
        generate_full_name()
    else:
        full_name_dup_list.append(full_name)
        print(full_name)



generate_full_name()
generate_full_name()
generate_full_name()
generate_full_name()
generate_full_name()
generate_full_name()
generate_full_name()
generate_full_name()

result: 
tony stark                                                                                                                                                                                             
tony wlliams                                                                                                                                                                                           
branden stark                                                                                                                                                                                          
branden smith                                                                                                                                                                                          
adam stark                                                                                                                                                                                             
agustin stark                                                                                                                                                                                          
agustin smith                                                                                                                                                                                          
stan smith      

每个结果都是不可重复的full_name。

但是,我不想使用一种方法来检查已经创建的数组。 因为数组的大小增加并且返回值的数量增加,所以不幸的是,该函数可能会继续递归执行。

这是另一种计划:像2深度陈述

import random
first_name = ['tony', 'adam', 'agustin', 'branden','stan']
last_name = ['smith', 'stark',  'wlliams']

class Index():
    idx_first = 0 
    idx_last = 0 


def generate_full_name():
    full_name=first_name[Index.idx_first] + " " + last_name[Index.idx_last]
    print(full_name)
    Index.idx_last=Index.idx_last+1
    if Index.idx_last== len(last_name)-1:
        Index.idx_first=Index.idx_first+1
        Index.idx_last=0

generate_full_name()
generate_full_name()
generate_full_name()
generate_full_name()
generate_full_name()
generate_full_name()
generate_full_name()

result: 
tony smith                                                                                                                                                                                             
tony stark                                                                                                                                                                                             
adam smith                                                                                                                                                                                             
adam stark                                                                                                                                                                                             
agustin smith                                                                                                                                                                                          
agustin stark                                                                                                                                                                                          
branden smith                                                                                                                                                                                          

但这似乎是非随机的。

问题:是否可以创建一个输出全名列表(如random)的函数,而不是检查现有的全名数组?

一个选择是拥有一组重复项,并使用生成器:

import random

first_name = ['tony', 'adam', 'agustin', 'branden','stan']
last_name = ['smith', 'stark',  'wlliams']

def generate_random_names(first, last):
    duplicates = set()
    while True:
        f = random.choice(first)
        l = random.choice(last)
        if (f, l) in duplicates:
            continue
        duplicates.add((f, l))
        yield f, l

for i, (f, l) in zip(range(1, 11), generate_random_names(first_name, last_name)):
    print('{}. {} {}'.format(i, f, l))

印刷品:

1. stan wlliams
2. adam wlliams
3. tony wlliams
4. adam stark
5. tony stark
6. branden wlliams
7. stan stark
8. agustin smith
9. branden stark
10. agustin wlliams

另一个版本使用itertools.productrandom.sample

import random
from itertools import product

first_name = ['tony', 'adam', 'agustin', 'branden','stan']
last_name = ['smith', 'stark',  'wlliams']

print(random.sample([*product(first_name, last_name)], 10))

印刷品:

[('stan', 'wlliams'), ('tony', 'stark'), ('agustin', 'smith'), ('agustin', 'wlliams'), ('tony', 'smith'), ('tony', 'wlliams'), ('stan', 'stark'), ('branden', 'stark'), ('stan', 'smith'), ('branden', 'wlliams')]

您知道可能有多少个名称-仅len(first) * len(last) 您可以生成此范围内的随机样本,然后进行一些数学运算以使组合与生成的数字匹配。 对于范围内的给定整数,映射将为:

f = first_name[s // len(last_name)]
l = last_name[s % len(last_name)]

使用than可以使用random.sample然后构建名称:

import random

first_name = ['tony', 'adam', 'agustin', 'branden','stan']
last_name = ['smith', 'stark',  'wlliams']

total = len(first_name) * len(last_name)
sam = random.sample(range(total), 10)

[f'{first_name[s // len(last_name)]} {last_name[s % len(last_name)]}' for s in sam]

结果:

['adam stark',
 'branden smith',
 'agustin smith',
 'stan wlliams',
 'tony smith',
 'stan stark',
 'branden wlliams',
 'agustin stark',
 'stan smith',
 'tony wlliams']

如果您尝试获取的数量超过总数(可能是您想要的总数random.sample()那么random.sample()会引发错误,因为您需要使用欺骗。

做到这一点的直接方法是使用哈希表:使用容易恢复的哈希码为每个字符串建立索引。 Python将为您轻松地做到这一点:将名称放入set ,然后检查set是否已经存在您生成的新名称。 做出新的选择,直到得到尚未使用的选择。

full_name_dup_set = set()

def generate_full_name():

    full_name = random.choice(first_name) + " " + \
                random.choice(last_name)

    while full_name in full_name_dup_set:
        full_name = random.choice(first_name) + " " + \
                    random.choice(last_name)

    full_name_dup_set.add(full_name)
    print(full_name)

如果您想要姓和名的全部组合,则可以在下面使用。 产品是sql中的笛卡尔乘积。

from itertools import product
[" ".join(list(name)) for name in product(first_name, last_name)]

结果:

['tony smith',
 'tony stark',
 'tony wlliams',
 'adam smith',
 'adam stark',
 'adam wlliams',
 'agustin smith',
 'agustin stark',
 'agustin wlliams',
 'branden smith',
 'branden stark',
 'branden wlliams',
 'stan smith',
 'stan stark',
 'stan wlliams']

这是一种将产生随机组合而无需预先生成所有名字对且没有迭代试验和错误循环的方法:

def generateNames():
    names  = dict()
    allLast = set(range(len(last_name)))
    while True:
        if not names: names = { iFirst:[] for iFirst in range(len(first_name)) }
        iFirst,usedLast = random.choice(list(names.items()))
        remainingLast  = list(allLast.difference(usedLast))
        iLast = random.choice(remainingLast)
        usedLast.append(iLast)
        if not allLast.difference(usedLast): del names[iFirst]
        yield first_name[iFirst]+" "+last_name[iLast]        
randomName = generateNames()

for _ in range(10): 
   print(next(randomName))

tony wlliams
agustin smith
stan stark
stan wlliams
tony smith
branden wlliams
tony stark
branden stark
agustin stark
stan smith

这个想法是要跟踪用于每个名字的姓氏。 它随机选择一个名字,然后从其余的那个名字中随机选择一个名字。 这样,您总是在首次尝试时获得独特的组合(与尝试/错误方法相对,随着获得更多名称,统计/方法会花费越来越多的时间)。

当使用姓氏的所有姓氏时,该名字将被消除,并且不符合后续随机选择的条件。

该解决方案是作为无限迭代器实现的,如果您到达组合的末尾,它将循环回到起点。 这样,您就可以在逻辑中的任意位置调用next(randomName),并且可以根据需要多次调用。

另一种使用更多内存但仍避免生成大量字符串的替代方法是生成复合索引的随机列表,并在需要时根据索引构建全名。 与预组装所有全名(但每个组合仍为一个整数)相比,这将占用更少的空间:

from collections import deque

firstCount = len(first_name)
lastCount  = len(last_name)
fullCount  = firstCount*lastCount
names = deque(random.sample(range(fullCount),fullCount))

def randomFullName():
    names.rotate(1)
    i = names[0]
    iFirst = i // lastCount
    iLast  = i % lastCount
    return first_name[iFirst] + " " + last_name[iLast]

for _ in range(10): 
    print(randomFullName())

旋转双端队列使函数可以继续生成名称,即使您调用它的次数超过组合次数也是如此。 这种方法不需要您事先知道将需要生成多少个名称。

def main():

    from random import sample

    first_names = ["Bob", "Tom", "Jay"]
    last_names = ["Jones", "Watson", "Smith"]

    all_possible_names = [f"{first} {last}" for first in first_names for last in last_names]

    print(sample(all_possible_names, k=4))

    return 0

if __name__ == "__main__":
    import sys
    sys.exit(main())
  1. 生成所有可能名称的列表。
  2. 随机抽取一个样本(就我而言,不能超过9个样本)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM