-2

I am looking for some help with loops. I have a name list, and I'm looking to sequentially message each profile from that list with a random user inputted message.

Ideally this would involve looping through the profileLink items while simultaneously looping through the nameList items so that I can build a new messageInput for each profile.

My code works, but currently has a lot of duplication and to build this to support a larger list will involve a lot of copying and pasting, as you can see below - How would you go about this?

messageInput0="Hi " + f'{namelist[0]}' + ", " + f'{choice(messageOptions)}'
messageInput1="Hi " + f'{namelist[1]}' + ", " + f'{choice(messageOptions)}'
messageInput2="Hi " + f'{namelist[2]}' + ", " + f'{choice(messageOptions)}'
messageInput3="Hi " + f'{namelist[3]}' + ", " + f'{choice(messageOptions)}'
messageInput4="Hi " + f'{namelist[4]}' + ", " + f'{choice(messageOptions)}'

webbrowser.open(profileLink[0])
time.sleep(6)
pyautogui.press('tab')
pyautogui.write(messageInput0, interval=random.uniform(0.03, 0.15))

with pyautogui.hold('command'):
    pyautogui.press('w')

webbrowser.open(profileLink[1])
time.sleep(6)
pyautogui.press('tab')
pyautogui.write(messageInput1, interval=random.uniform(0.03, 0.15))

with pyautogui.hold('command'):
    pyautogui.press('w')

webbrowser.open(profileLink[2])
time.sleep(6)
pyautogui.press('tab')
pyautogui.write(messageInput2, interval=random.uniform(0.03, 0.15))

with pyautogui.hold('command'):
    pyautogui.press('w')

    webbrowser.open(profileLink[3])
time.sleep(6)
pyautogui.press('tab')
pyautogui.write(messageInput3, interval=random.uniform(0.03, 0.15))

with pyautogui.hold('command'):
    pyautogui.press('w')

    webbrowser.open(profileLink[4])
time.sleep(6)
pyautogui.press('tab')
pyautogui.write(messageInput4, interval=random.uniform(0.03, 0.15))

with pyautogui.hold('command'):
    pyautogui.press('w')

EDIT: After trying the top answer, I got the error that list object has no attribute 'replace'

Worth mentioning my list is built using str.replace/str.split functions, like so:

profileLink = open("profiles.txt").read().splitlines()

profileLink = [item.replace("+","name=") for item in profileLink]
newLinks = [item.replace("%","name=") for item in profileLink]
nameList = [i.split("name=")[1] for i in newLinks]

EDIT 2: First edit was actually an unrelated error. Fixed now.

dan.rad
  • 35
  • 8
  • 1
    Does this answer your question? [How do I iterate through two lists in parallel?](https://stackoverflow.com/questions/1663807/how-do-i-iterate-through-two-lists-in-parallel) – Donnie Sep 28 '22 at 10:51

3 Answers3

5

Like so.

  • Use zip to "zip up" the name and profile link and you don't have to keep track of loop indexes.
import random
import time
import pyautogui
import webbrowser

namelist = ["a", "b", "c", "d"]
profilelink = ["q", "w", "e", "r"]
messageOptions = ["bye", "hello"]

for name, link in zip(namelist, profilelink):
    message = f"Hi {name}, {random.choice(messageOptions)}"

    webbrowser.open(link)
    time.sleep(6)
    pyautogui.press("tab")
    pyautogui.write(message, interval=random.uniform(0.03, 0.15))

    with pyautogui.hold("command"):
        pyautogui.press("w")
AKX
  • 152,115
  • 15
  • 115
  • 172
  • This almost got me there, some added context: I am creating the profileLink list and nameList with split and replace operations `profileLink = open("profiles.txt").read().splitlines() profileLink = [item.replace("+","name=") for item in profileLink] newLinks = [item.replace("%","name=") for item in profileLink] nameList = [i.split("name=")[1] for i in newLinks] ` As a result when I run this code, I am getting an error that the list object has no attribute 'replace' – dan.rad Sep 28 '22 at 11:15
  • I've tried formatting as a string literal but it seems the webbrowser command won't work on a string literal? – dan.rad Sep 28 '22 at 11:17
  • 1
    That error is unrelated to this code, and as far as I can see there's nothing there that could throw that error. – AKX Sep 28 '22 at 11:45
  • You are correct. This is solved now. Thank you for your help. – dan.rad Sep 29 '22 at 16:10
1

This is how I'd do it:

import random
import time
import webbrowser


def messageInput(nameList, profileLink):
    for name in nameList:
        message = "Hi " + f'{name}' + ", " + f'{choice(messageOptions)}'
        for profile in profileLink:
            webbrowser.open(profile)
            time.sleep(6)
            pyautogui.press('tab')
            pyautogui.write(message, interval=random.uniform(0.03, 0.15))

        with pyautogui.hold('command'):
            pyautogui.press('w')
Sunderam Dubey
  • 1
  • 11
  • 20
  • 40
0

Use a for loop:

for i in range(len(profileLink)):
    webbrowser.open(profileLink[i])
    time.sleep(6)
    pyautogui.press('tab')
    message = f'Hi {namelist[i]}, {choice(messageOptions)}'
    pyautogui.write(message, interval=random.uniform(0.03, 0.15))
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • Using `for i in range(len(...))` is not quite Pythonic... – AKX Sep 28 '22 at 10:53
  • 1
    @AKX What makes it... non-pythonic? – Mathias R. Jessen Sep 28 '22 at 10:56
  • The Pythonic way to iterate over a single iterable with indices, you'd use `for i, x in enumerate(l)`, but since you're only using `i` to be able to index into the other "parallel" list you don't need it at all; you'd use `for x, y in zip()` to iterate them in in parallel. – AKX Sep 28 '22 at 11:46
  • 1
    @AKX `zip()` is obviously a better solution here, but I wasn't aware iterating over `range(len(...))` (vs directly over `enumerate(...)`) was considered an antipattern, thanks! – Mathias R. Jessen Sep 28 '22 at 11:48
  • 1
    One more data point (that's not relevant in _this_ case): `range(len())` won't work if you can't know the length of iterable, and considering [There should be one obvious way to do it. ](https://peps.python.org/pep-0020/) using a different pattern for lengthable iterables vs. others seems non-Pythonic :) – AKX Sep 28 '22 at 11:50