1

I'm trying to build a name, surname combos from a list. But failed to do this in my loop function. Appreciate some help.

names = ['Appleby', 'James']
nn = ['James', 'Jim', 'Jimmy', 'Jimmie', 'Jamie', 'Jem']
combos = []
for g in nn:
    names[1] = g
    combos.append(names)
print(combos)

The results :

[['Appleby', 'Jem'],
 ['Appleby', 'Jem'],
 ['Appleby', 'Jem'],
 ['Appleby', 'Jem'],
 ['Appleby', 'Jem'],
 ['Appleby', 'Jem']]

What I would like to achieve is :

[['Appleby', 'James'],
 ['Appleby', 'Jim'],
 ['Appleby', 'Jimmy'],
 ['Appleby', 'Jimmie'],
 ['Appleby', 'Jamie'],
 ['Appleby', 'Jem']]
girlrilaz
  • 29
  • 1
  • 7

3 Answers3

4

I believe you are looking for all combinations of names in two lists. You can use this for that -

combos = [[name, n] for n in nn for name in names]

If you want combinations with just 'Appleby'. Use

combos = [[names[0], n] for n in nn]

The problem is when you are updating name[1] = g. It is updating the same list which is being appended multiple times in combos. For additional information check out mutable and immutable objects in python.

For specific information on the list += operator, see this answer.

Jaideep Shekhar
  • 808
  • 2
  • 7
  • 21
Saurabh Sangwan
  • 417
  • 2
  • 6
  • Thanks, if names has 3 elements, eg: names = ['Appleby', 'Damien', 'James'] , how do I make sure the combos only happens to index 2 = James? – girlrilaz Oct 29 '19 at 23:14
1

Or use itertools.cycle with zip:

from itertools import cycle
combos = list(zip(cycle([names[0]]), nn))
print(combos)

Output:

[('Appleby', 'James'), ('Appleby', 'Jim'), ('Appleby', 'Jimmy'), ('Appleby', 'Jimmie'), ('Appleby', 'Jamie'), ('Appleby', 'Jem')]
U13-Forward
  • 69,221
  • 14
  • 89
  • 114
0

The reason why your code was "failing" was because when you changed the value of names[1] you essentially changed the values inside combos. For the sake of this answer, I will break your names list into names[0], and names[1]

When you were appending to combos, in psuedo-code you were writing it as

combos.append([names[0], names[1]])

Lists are a bunch of adjacent pointers. If you have a list sized 10, you have 10 pointers (which point to a value). It wouldn't make sense to send the pointer elsewhere as it is neatly stored in sequential order. Therefore when you change the value of a slot in the list, you merely changed the variable that the pointer was pointing to.

When you appended names[1] into the list, you gave it a "pointer". Which gives:

combos = ([[names[0], names[1]], [names[0], names[1]], ...., [names[0], names[1]]])

To avoid passing pointers into combo, you can just pass a variable. Variables aren't pointing to anything therefore when you change a variable, you change the var itself and not the entire combos list.

names = ['Appleby', 'James']
nn = ['James', 'Jim', 'Jimmy', 'Jimmie', 'Jamie', 'Jem']
combos = []
for g in nn:
    combos.append([name[0],g])
print(combos)
  • Thanks, if names has 3 elements, eg: names = ['Appleby', 'Damien', 'James'] , how do I make sure the combos only happens to index 2 = James? – girlrilaz Oct 29 '19 at 23:21
  • I'm not sure if I understand this right. I'm assuming that you want to append names[1] to combos list. Then in that case you can say ``` g = names[1] ``` and then ``` combos.append(g) ``` – loyal renegade Oct 31 '19 at 00:52