2

Pardon if the question is titled confusingly. I couldn't think of a better way to word it. Anyway, I have a Python program that accepts a list of first names and a list of last names. It then "splits" the two into all of their combinations, with a maximum of 5 results. The code explains it better:

def getLists(firstNames, lastNames, resultCount):
    firstNameCount = len(firstNames)
    lastNameCount = len(lastNames)

    if firstNameCount >= resultCount:
        # Return the last name list as is.
        return [firstNames[i * firstNameCount / resultCount:(i + 1) * firstNameCount / resultCount] for i in xrange(resultCount)], [lastNames for _ in xrange(resultCount)]

    else:
        lastNameLists = []
        firstNameLists = [[firstNames[i % firstNameCount]] for i in xrange(resultCount)]

        for i in xrange(resultCount):
            firstName = firstNameLists[i]
            total = firstNameLists.count(firstName)
            already = total - firstNameLists[i:].count(firstName)
            lastNameLists.append(lastNames[already * lastNameCount / total:(already + 1) * lastNameCount / total])

        # Return the last names, split depending on how many results and first names.
        return firstNameLists, lastNameLists

If there are less first names than the maximum (5), the first names are repeated until the maximum and the last names are distributed among the first names:

firstNames = ['firstName{}'.format(i) for i in xrange(1, 3)]
lastNames = ['lastName{}'.format(i) for i in xrange(1, 8)]
comboCount = len(firstNames) * len(lastNames)
resultCount = min(comboCount, 5)
firstNameLists, lastNameLists = getLists(firstNames, lastNames, resultCount)

for i in xrange(resultCount):
    print 'Result #{}:\nFirst Names: {}\nLast Names: {}'.format(i + 1, firstNameLists[i], lastNameLists[i])
    print

Output:

Result #1:
First Names: ['firstName1']
Last Names: ['lastName1', 'lastName2']

Result #2:
First Names: ['firstName2']
Last Names: ['lastName1', 'lastName2', 'lastName3']

Result #3:
First Names: ['firstName1']
Last Names: ['lastName3', 'lastName4']

Result #4:
First Names: ['firstName2']
Last Names: ['lastName4', 'lastName5', 'lastName6', 'lastName7']

Result #5:
First Names: ['firstName1']
Last Names: ['lastName5', 'lastName6', 'lastName7']

If there are more first names than the maximum (5), the first names are distributed as evenly as possible and the last names are copied for each:

firstNames = ['firstName{}'.format(i) for i in xrange(1, 8)]
lastNames = ['lastName{}'.format(i) for i in xrange(1, 8)]
comboCount = len(firstNames) * len(lastNames)
resultCount = min(comboCount, 5)
firstNameLists, lastNameLists = getLists(firstNames, lastNames, resultCount)

for i in xrange(resultCount):
    print 'Result #{}:\nFirst Names: {}\nLast Names: {}'.format(i + 1, firstNameLists[i], lastNameLists[i])
    print

Output:

Result #1:
First Names: ['firstName1']
Last Names: ['lastName1', 'lastName2', 'lastName3', 'lastName4', 'lastName5', 'lastName6', 'lastName7']

Result #2:
First Names: ['firstName2']
Last Names: ['lastName1', 'lastName2', 'lastName3', 'lastName4', 'lastName5', 'lastName6', 'lastName7']

Result #3:
First Names: ['firstName3', 'firstName4']
Last Names: ['lastName1', 'lastName2', 'lastName3', 'lastName4', 'lastName5', 'lastName6', 'lastName7']

Result #4:
First Names: ['firstName5']
Last Names: ['lastName1', 'lastName2', 'lastName3', 'lastName4', 'lastName5', 'lastName6', 'lastName7']

Result #5:
First Names: ['firstName6', 'firstName7']
Last Names: ['lastName1', 'lastName2', 'lastName3', 'lastName4', 'lastName5', 'lastName6', 'lastName7']

How could I make getLists more efficient, readable, and/or cleaner?

Hank
  • 125
  • 1
  • 11
  • Look at `itertools` module and https://stackoverflow.com/questions/464864/how-to-get-all-possible-combinations-of-a-list-s-elements – dmitryro Jan 14 '19 at 02:59
  • Use product in itertools, I wonder why you wanna generate names, actually you can use https://github.com/joke2k/faker faker to fake names as you wish. – Menglong Li Jan 14 '19 at 03:02
  • ```itertools``` doesn't seem to have anything I see that solves the problem described in the question. – Hank Jan 14 '19 at 03:04
  • It does have all you need, it obviously requires some effort to exclude those results you don't need. – dmitryro Jan 14 '19 at 03:07
  • I don't see any functions in ```itertools``` that would make this code any more efficient, readable, and/or cleaner. – Hank Jan 14 '19 at 03:13

1 Answers1

0

The demo is Python3, if you use Python2, try to make a little code change if possible:

firstNames = ['firstName{}'.format(i) for i in range(1, 3)]
lastNames = ['lastName{}'.format(i) for i in range(1, 2)]

from itertools import product, islice

print(list(islice(product(firstNames, lastNames), 5)))

the islice ensure it returns the first 5 result, if the results is less than 5, it's still OK.

Menglong Li
  • 2,177
  • 14
  • 19