Recommend a data structure please

I’m writing a program to pick a Psalm from the Bible at random and display it.
So for example, if the random number is 23, it will pick Psalm 23 and display Psalm 23.
Each time a Psalm is picked the Psalm’s number will be recorded in a file called “ChaptersChosen.txt”. This will allow statistics such as how many times each Psalm has been picked, and which Psalms have not been picked yet.

I have the book of Psalms in a text file formatted like:
1:1 Blessed is the man that walketh not in the counsel of the ungodly, nor standeth in the way of sinners, nor sitteth in the seat of the scornful.
1:2 But his delight is in the law of the LORD; and in his law doth he meditate day and night …
150:6 Let every thing that hath breath praise the LORD. Praise ye the LORD.

I’ve also got it in a dictionary format like:
{“1:1”: “Blessed is the man that walketh not in the counsel of the ungodly, nor standeth in the way of sinners, nor sitteth in the seat of the scornful.”, “1:2”: “But his delight is in the law of the LORD; and in his law doth he meditate day and night.”, …}

and I have considered a dictionary of dictionaries like:
{“1”: {“1:1”: “Blessed is the man that walketh not in the counsel of the ungodly, nor standeth in the way of sinners, nor sitteth in the seat of the scornful.”, “1:2”: “But his delight is in the law of the LORD; and in his law doth he meditate day and night.”, “1:3”: “And he shall be like a tree planted by the rivers of water, that bringeth forth his fruit in his season; his leaf also shall not wither; and whatsoever he doeth shall prosper.”, “1:4”: “The ungodly are not so: but are like the chaff which the wind driveth away.”, “1:5”: “Therefore the ungodly shall not stand in the judgment, nor sinners in the congregation of the righteous.”, “1:6”: “For the LORD knoweth the way of the righteous: but the way of the ungodly shall perish.”}, … }

My Question: What data structure would you recommend and why?
I’ve tried using all 3 and I wonder if I am going about it in the best way.

I think the right data structure will depend on how much work you want
to put it up front, and how likely it is that you are planning to extend
this with (say) translations, other books of the bible, etc.

If you don’t care about extending it, I would use a nested dictionary:

{1: {1: "Blessed is the man that walketh not...", 
     2: "But his delight is in the law...",
     },
 150: {6: "Let every thing that hath breath...", }
 }

and imbed it directly in your source code.

Notice that I’m using numeric keys 1, 2, … not strings. That makes it
a bit easier to generate them randomly.

If you are willing to put in a bit more work up front, I would write the
Psalms out into a text file, as plain text in the usual format:

1:1 Blessed is the man that walketh ...
1:2 But his delight is ...

Write a program to read that text file, parse it into chapters and
versus, and load them into a dict as above. You will probably find that
on any modern computer, doing that parsing will be close enough to
instantaneous that you won’t notice the time it takes.

Although that’s lots of work up front, it will mean that you easily
change the text file to another version of the Psalms (different
translation), or even another book, without needing to change the source
code.

Personally, I would probably aim for the second. But it will require
more work to parse the text file and split it into chapters and versus.

1 Like

Thank you very much for your reply.

Yes I thought of doing something to create my nested dictionary file but don’t know where to start for that.
I’m using KJV as it’s in the public domain. I might just manually created the nested dictionary. I’ve already done the first 11 chapters for this.

Thanks again.

Hi, I would suggest to store Psalms as a list, and then use choice function from random library,

from random import choice
# I'm assuming that you have a function that loads Psalms as a list from a file or database
Psalms = load_psalms()
psalm_of_today = choice(Psalms)

If you still want to use a dictionary, parsing the textfile is very important, I would recommend the re module, in order to parse the file, this is my approach:

from random import choice
from re import match

psalms = {}

with open('salms', 'r') as f: 
    for l in  f.readlines():
        g = match(r"^(\d+:[\d-]+) (.+)$", l)
        psalms[g.group(1)] = g.group(2)


psalm = choice(list(psalms)) # you'll get the chapter:versus

psalm_text = psalms[psalm] # the actual psalm text

#counter for selected psalms

counter = {}

try:
    counter[psalm] += 1
except:
    counter[psalm] = 1

Let me know if you have questions regarding the code above.

I’m assuming that the text file has the following format:

37:35 I have seen the wicked/in great power, and spreading/himself like a green bay tree.
37:36 Yet he passed away,/and, lo, he was not:/yea, I sought him,/but he could not be found.
39:4 LORD, make me to know mine end,/and the measure of my days,/what it is; that I may know/how frail I am.

That looks like a good format to me. That is equivalent to JSON, correct? In my opinion that format would be good. No need to design a specialized format. And I think it would be better to store the file separate from the Python script.

Would it be possible to store the text in a compressed format, just to save space? And then the compressed data could be expanded during execution.

Here is a wild idea. Store the data in a database. There could be a table of books and for each book there would be a table of chapters and for each chapter there would be verses. Databases are capable of creating indexes, it might be possible to create an index of the data.

That description sounds like I am suggesting separate tables for each chapter but I really mean a table of chapters with a relationship from the book to the chapters, and something corresponding for verses. The type of thing a database person would do.

That could be a table in the database. Related data could be stored, such as date.

My choice would depend on how I would want to be using the program later on. To me the simplest solution for the current requirements would be to use non-nested dictionary or file.

I would not use list because I find the key:value separation best for this use case, and you can always do the random choices from dictionary as well. Like so:


psalms = {
    "1:1": "Blessed is the man that walketh not in the counsel of the ungodly, nor standeth in the way of sinners, nor sitteth in the seat of the scornful.",
    "1:2": "But his delight is in the law of the LORD; and in his law doth he meditate day and night."
}

random_key = random.choice(list(psalms.keys()))

print(random_key, psalms[random_key])

Also, this kind of solution does not require using numeric keys, as we do not need random numbers while using choice. The nested structure maybe more future proof though if you would like to extend this in some way.

Thankyou for your ideas.

Thank you for this. I had not known that.