1

This is my first time submitting here, so please bear with me on formatting.

So, I have a normal list of strings like:

name = ["Michael", "Helen", "Mike", "Joe", "Michael"]

I need to append these to another list if they don't repeat, and then later print out that list. So the next list would be like

norepeat_list = ["Michael", "Helen", "Mike", "Joe"]

Which I've already done and didn't have issues with. The problem is I'm not just appending those names, each name has another value associated with it in another list of times (also strings), and I need that too. So I've been appending both the name and the times at the same time in a list like

norepeat_list.append(name[i], time[i])

Which then makes the result a 2d list. So I don't know how to make it so that the program checks each list in the list for the original name value, and the only solution I've found is 'any' or some import stuff, and I can't do that.

So far I have:

name = ["Michael", "Helen", "Mike", "Joe", "Michael"]
time = ["08:42:39", "08:39:56", "08:58:43", "09:04:03", "05:32:54"]

norepeat_list = []
for i in range(len(name[i])):
     if name[i] not in norepeat_list:
         norepeat_list.append(name[i])

for i in norepeat_list:
     print(i)

I've tried appending the timestamp at the same time and adding another layer of for j in ..., but I can't get anything to work.

accdias
  • 5,160
  • 3
  • 19
  • 31

3 Answers3

2

The closest working code I can think of to your example is:

name = ["Michael", "Helen", "Mike", "Joe", "Michael"]
time = ["08:42:39", "08:39:56", "08:58:43", "09:04:03", "05:32:54"]

seen_names = []
norepeat_list = []
for i in range(len(name)):
     if name[i] not in seen_names:
         seen_names.append(name[i])
         norepeat_list.append((name[i], time[i]))

for name_time in norepeat_list:
     print(name_time)

but note that I've introduced an extra seen_names array to keep track of things you've already seen. Having this extra list is bad for maintenance as you need to make sure both lists stay in sync with each other. It's also bad for performance as checking whether an item is in a list takes time proportional to the length of the list, i.e. it gets slower for longer lists. It would be better to use a set to track the items you've seen, as this wouldn't slow down as more items get added.

A more significant improvement would be to use a dictionary/dict which allows you to associate arbitrary data (i.e. your times) with a set of items (i.e. your names). A naive translation of the above code would be:

names = ["Michael", "Helen", "Mike", "Joe", "Michael"]
times = ["08:42:39", "08:39:56", "08:58:43", "09:04:03", "05:32:54"]

names_and_times = {}
for i in range(len(names)):
    if names[i] not in names_and_times:
        names_and_times[names[i]] = times[i]

for name_time in names_and_times.items():
    print(name_time)

Note that I've switched to a naming convention where plurals indicate a container of multiple values.

This could be improved by noticing that it repeats names[i] a lot. An way to reduce this would be to use enumerate:

names_and_times = {}
for i, name in enumerate(names):
    if name not in names_and_times:
        names_and_times[name] = times[i]

or alternatively, you could use zip as many other answers have suggested:

names_and_times = {}
for name, time in zip(names, times):
    if name not in names_and_times:
        names_and_times[name] = time

another variant would be to exploit the fact that dictionaries can't have duplicates, so setting a dictionary item with the same item multiple times would just change the value rather than adding a new entry:

names_and_times = {}
for name, time in zip(names, times):
    names_and_times[name] = time

Note that this leaves the last time set for each name rather than the first. Your question doesn't seem to express a preference, but this could be changed by iterating in reverse order:

names_and_times = {}
for name, time in zip(reversed(names), reversed(times)):
    names_and_times[name] = time

Next we could use a dictionary comprehension, which cleans the above up to:

names_and_times = {
    name: time
    for name, time in zip(names, time)
}

Finally we get to my original comment about things being magical, which exploits this usage of zip and the fact that passing an Iterable of pairs causes the constructor of a dict to build a dictionary where the first item of each pair is the key and the second item is the value:

names_and_times = dict(zip(names, times))

or if you want the first time for each name you could do:

names_and_times = dict(zip(reversed(names), reversed(times)))

All of my examples leave names_and_times as a dictionary, but if you wanted to convert back to a list you can just do:

names_and_times = list(names_and_times.items())
Sam Mason
  • 15,216
  • 1
  • 41
  • 60
-1

In this case I advise you use the "zip" function.

for n,t in zip(name,time):
    print(n,t)

this will zip the two lists together and you have access to the values of both lists.
-1

As you wrote "each name has another value associated with it in another list of times" I assume name and time has the same length, then something like this would work

zip produces a tuple of elements from both lists on the same position, so it will maintain the order, and skip elements with non-unique names (because they added to the seen):

    seen = set()
    result = []
    for n, t in zip(name, time):
        if n not in seen:
            seen.add(n)
            result.append((n, t))
    print(result)
svfat
  • 3,273
  • 1
  • 15
  • 34