Posts: 21
Threads: 5
Joined: Jul 2020
Aug-06-2023, 11:46 AM
(This post was last modified: Aug-06-2023, 12:14 PM by User3000.)
I have already posted all my code in in the initial post.
I think the solution to my problem is this bit here posted by @ Yoriz, makes sense:
"To alter the state of which item is selected you would need to store that state to be recalled each time the code is run."
I just need an example of how to do it.
Posts: 6,818
Threads: 20
Joined: Feb 2020
Aug-06-2023, 12:17 PM
(This post was last modified: Aug-06-2023, 12:27 PM by deanhystad.)
The code you posted works correctly.
for applicant_name in new_applicants():
print(f'Here we have applicant {applicant_name}.') I want to see an example of your code where the generator is not yielding the results you want.
Yoriz is asking if you want your program to remove applicants as they are used by your program. You run your program and it asks for two applicants. The applicants are Mathew and Michael. You run your program again and ask for an applicant. The applicant is Natalie. You run your program again, ask for an applicant and are told there are no remaining applicants.
Is that what you want? If so, you will need an external applicant reference that is modified each time you ask for an applicant. This could be as simple as a file, where you read and remove the first applicant each time your function is called.
That is not what you asked for in your first post. You asked for a function that acts like an iterator. Each time the function is called it returns the next value from the list. You could write such a thing, but why? You can already get this behavior using an iterator, as I demonstrated in my reply. You could bundle this up with some syntactic sugar to make it look like a function call.
job_applicants = {'applicants': {'names': [
{'name': 'Matthew', 'key2': '...', 'key3': 'value1'},
{'name': 'Michael', 'key2': '...', 'key3': 'value2'},
{'name': 'Natalie', 'key2': '...', 'key3': 'value3'}]}}
def applicant_generator():
for each_applicant in job_applicants['applicants']['names']:
applicant_name = each_applicant['name']
yield applicant_name
applicant_iterator = applicant_generator()
def new_applicant():
return next(applicant_iterator)
print(new_applicant())
print(new_applicant())
print(new_applicant()) This does what you asked, but I think it is a bad idea. Why hide that you are using an iterator?
Posts: 21
Threads: 5
Joined: Jul 2020
Aug-06-2023, 12:23 PM
(This post was last modified: Aug-06-2023, 12:25 PM by User3000.)
I don't need to remove the applicant. In fact, I don't want to remove it. I want to cycle through the applicants. Each time a different name should appear. The order of the applicant matters.
So far I go to IDLE Python 3.8 and load up my .py file and hit the "Run" button and every time I hit "Run" I get the same name. Matthew. Michael and Natalie don't show up.
Posts: 6,818
Threads: 20
Joined: Feb 2020
Aug-06-2023, 12:30 PM
(This post was last modified: Aug-06-2023, 12:57 PM by deanhystad.)
You want your program to act differently each time it is run? To do that you need to change the applicant list each time you run. That will require having an external resource that is modified each time you ask for an applicant.
import json
def get_applicant():
# Load applicants from file
with open("applicants.json", "r") as file:
applicants = json.load(file)
# Get first applicant. Move to end of applicant list
names = applicants['applicants']['names']
applicant = names.pop(0)
names.append(applicant)
# Save modified applicant list
with open("applicants.json", "w") as file:
json.dump(applicants, file, indent=4)
return applicant["name"]
print(get_applicant()) The program uses a file to hold the names. This program creates the json format file use by the program above.
import json
job_applicants = {'applicants': {'names': [
{'name': 'Matthew', 'key2': '...', 'key3': 'value1'},
{'name': 'Michael', 'key2': '...', 'key3': 'value2'},
{'name': 'Natalie', 'key2': '...', 'key3': 'value3'}]}}
with open("applicants.json", "w") as file:
json.dump(job_applicants, file, indent=4) Here it is as 1 program.
mport json
def get_applicant():
# Load applicants from file
try:
with open("applicants.json", "r") as file:
applicants = json.load(file)
except FileNotFoundError:
applicants = {'applicants': {'names': [
{'name': 'Matthew', 'key2': '...', 'key3': 'value1'},
{'name': 'Michael', 'key2': '...', 'key3': 'value2'},
{'name': 'Natalie', 'key2': '...', 'key3': 'value3'}]
}}
# Get first applicant. Move to end of applicant list
names = applicants['applicants']['names']
applicant = names.pop(0)
names.append(applicant)
# Save modified applicant list
with open("applicants.json", "w") as file:
json.dump(applicants, file, indent=4)
return applicant["name"]
print(get_applicant())
Posts: 21
Threads: 5
Joined: Jul 2020
Would itertools.cycle not work in my case?
Posts: 6,818
Threads: 20
Joined: Feb 2020
Aug-06-2023, 01:07 PM
(This post was last modified: Aug-06-2023, 01:07 PM by deanhystad.)
Would itertools.cycle not work in my case?
No. Cycle will restart the sequence when you reach the end. It will not remember what you were doing the last time you ran the program. For that. For that, you need something to remember where you were. See my previous post for example.
Another approach is save the index of the next applicant in a file.
applicants = {'applicants': {'names': [
{'name': 'Matthew', 'key2': '...', 'key3': 'value1'},
{'name': 'Michael', 'key2': '...', 'key3': 'value2'},
{'name': 'Natalie', 'key2': '...', 'key3': 'value3'}]
}}
def get_applicant():
# Load index from file
try:
with open("applicants.index", "r") as file:
index = int(file.read())
except (FileNotFoundError, ValueError):
index = 0
applicant = applicants['applicants']['names'][index]
# Update the index file
index = (index + 1) % len(applicants['applicants']['names'])
with open("applicants.index", "w") as file:
file.write(str(index))
return applicant["name"]
print(get_applicant())
Posts: 21
Threads: 5
Joined: Jul 2020
Aug-06-2023, 01:17 PM
(This post was last modified: Aug-06-2023, 01:17 PM by User3000.)
Eureka, it works!
Yes, finally
Thank you so much.
edit: indeed, the version with an index file works just as fine. Awesome!
(Aug-06-2023, 01:07 PM)deanhystad Wrote: Would itertools.cycle not work in my case?
No. Cycle will restart the sequence when you reach the end. It will not remember what you were doing the last time you ran the program. For that. For that, you need something to remember where you were. See my previous post for example.
I think this is rather interesting. I have actually a similar scenario where it doesn't need to remember the last position. So it can restart at the beginning. Import thing is to cycle through the different names.
So then itertools.cycle would work right?
If it's not too much to ask for, what would that look like code wise? With itertools.cycle.
Impressed
Posts: 6,818
Threads: 20
Joined: Feb 2020
Next time post an example of your code that shows it not working. Lucky for you that Yoriz guessed the issue or we would still be trying to get to the root of the problem.
itertools.cycle works if you want to cycle through a sequence forever. Cycling through 'ABC' results in ABCABCABCABC... If you don't use cycle, the sequence is played out once and a StopIteration exception is raised with you run out of values.
from itertools import cycle
a = cycle('ABC')
b = iter('ABC')
while True:
print("a", next(a))
print("b", next(b)) Output: a A
b A
a B
b B
a C
b C
a A
Traceback (most recent call last):
File "c:\Users\djhys\Documents\python\musings\junk.py", line 8, in <module>
print("b", next(b))
^^^^^^^
StopIteration
Posts: 21
Threads: 5
Joined: Jul 2020
Absolutely! let's jus say describing the problem is always the hardest part.
About itertools.cycle:
this is again like before. Not what I want.
So whenever I run the script it should start from the beginning and cycle through each name. Not printing everything at once.
I am considering this because it doesn't involve another file like the index file or a json.
Appreciated!
Posts: 6,818
Threads: 20
Joined: Feb 2020
If anything is "printing everything at once", that is your code, not anything to do with iterators. If you want to use an iterator outside a for loop, use next() as I showed in my first response to your post.
Again, please post an example showing what your are trying to do and describe how it doesn't work.
|