Home > Software engineering >  create a dictionary of with key as the attribute and value as model object
create a dictionary of with key as the attribute and value as model object

Time:01-03

Say i have this table:

class Blog(models.Model)
  title = models.CharField()
  body = models.CharField()
  author = models.ForeignKey(Author)

I need to create 3 rows with the title (title_1, title_2, title_3). I need to fetch all the blog objects and create a dictionary with key as the title and value as blog object.

blog_dict = {'title_1': <blog_object_1>, 'title_2': <blog_object_2>, 'title_2': <blog_object_3>}

I have 1 million records to work. Is there any efficient way to do it?

CodePudding user response:

this might do this task

blog_dict = {}
blogs = Blog.objects.all()
for blog in blogs:
    blog_dict[blog.title] = blog

as @ZXYNINE mentioned in the comment section below, it could be done with a single line instead of full form of for loop like so:

blog_dict  = { blog.title:blog for blog in blogs}

I find the first method is better for beginners, but also it worth to mention the other method as well.

CodePudding user response:

If i understood you correct, you wish to create a dict that essentially maps names of each blog obj to the instance right? This will really come down to specific functions you use and how you create the dictionary. What i would do is create the dictionary WHILE you initalise each object instead of iterating overthem after they have been created, but that assumes you have access to the init function of the class and dont need the objects for anything else until this point. Im not quite sure what you mean by "I need to create 3 rows" in combination with "I have 1 million records to work.", so I cant give you an exact method to try. Lets assume what you meant was you wanted to divide your 1 million records into a table that is (1mil/3)columns by 3rows. I would do something like this:

class Blog(models.Model):
    title = models.CharField()
    body = models.CharField()
    author = models.ForeignKey(Author)

Blogs:'list[Blog]' = [Blog,]*1000000


BlogTable = []
BlogRowBuffer = {}
# Using an int to count instead of len(BlogRowBuffer) to save processing power
BlogRowCount = 0

for blog in Blogs:
    BlogRowBuffer[blog.title] = blog
    BlogRowCount  =1
    #Once you add the third item to the row buffer, the buffer is made into a column in the table.
    # And the values reset to start all over.
    if BlogRowCount == 3:
        BlogTable.append(BlogRowBuffer)
        BlogRowBuffer = {}
        BlogRowCount = 0

The problem is, no matter how you tackle it, you must iterate over 1million objects and that will always take a fair amount of time. You should use built-in python functions wherever possible as they are written in C and are generally far faster than anything else. You should also look into some python libraries which could help with this. I know that deque provides faster speeds when it comes to pop left/right but I dont know any off the top of my head that will speed this up.

Additionally, if you know the exact number of objects, you can pre-allocate space to a list before doing anything and then just modify the list by indexing which is faster than appending: see this link. That link also shows that list comprehensions can be faster but I know from experence that you should always compare the times yourself as it depends on HOW you use the different methods.

  • Related