0

I have a function which creates data

from faker import Faker
import pandas as pd
import random

def create_rows_faker(num=1, name_col = True, address_col = True, email_col = False):
    output = []
    for x in range(num):
        out = {}
        if name_col:
            out["name"] = fake.name()
        if address_col:
            out["address"] = fake.address()
        if email_col:
            out["email"] = fake.email()
        output.append(out)
    return output

but I want to remove the multiple if statements inside the for loop. What is the best method to improve this?

8
  • 2
    Whats wrong with them? Commented May 4, 2022 at 14:32
  • the response is known for each iteration Commented May 4, 2022 at 14:33
  • I'm not sure what that means Commented May 4, 2022 at 14:34
  • is there a way to take the ifs outside of the for loop for sake of speed and beauty? Commented May 4, 2022 at 14:35
  • No, there isn't Commented May 4, 2022 at 14:37

4 Answers 4

1

You can use kwargs and dictionary

def create_rows_faker(num=1, **kwargs):
    output = []
    es = {"name": fake.name(), "address": fake.address(), "email": fake.email()}
    for x in range(num):
        output.append({key: es[key] for key in kwargs.keys() if kwargs.get(key) })
    return output

create_rows_faker(num=1, name=True, address=True, email=True)
Sign up to request clarification or add additional context in comments.

Comments

1

Instead of taking the columns as separate arguments, use a list of column names. You can then loop over this list, and fill in out with the corresponding fakes, using getattr() to call the methods dynamically.

from copy import deepcopy

def create_rows_faker(num=1, columns):
    output = []
    for _ in range(num):
        out = {col: getattr(fake, col)() for col in columns}
        output.append(out)
    return output

4 Comments

It is repeating the same fake in each row though
I didn't realize that fake.XXX() returns a different result each time.
ah, did you mean to store output as a list?
yes, just as in your original code
1

I'm not sure if this really is going to be any faster, because copying dictionaries does take at least as much time as doing if statements, but you can create the dictionary once and then copy it in to your output as needed.

def create_mock_rows(num: int = 1, 
                     name_col: bool = True, 
                     address_col: bool = True, 
                     email_col: bool = True) -> list:
    out = {
        "name": fake.name() if name_col else None,
        "address": fake.address() if address_col else None,
        "email": fake.email() if email_col else None,
    }
    return [ {k: v for k, v in out.items() if v is not None} for _ in range(num)]

Another option is to leverage **kwargs:

def create_mock_rows(num: int = 1, **kwargs) -> list:
    return [{k: getattr(fake, v)() for k, v in kwargs.items()} for _ in range(num)]

I admit I don't love this, though, because kwargs could be anything, and there is some chance of this just failing or giving you a weird result if improperly called.

3 Comments

Only problem is this generates the same name, address, email each iteration
@user309575 Ah... well, it was unclear that the fake.thing() function returns new items each time. To be honest, what you probably want to write is a generator function that spits out a single dictionary and can be called howmany ever times. But that doesn't solve the question you asked about.
@user309575 I also added an option that combines Barmar and Tripathi's answers.
0

Almost every language provides a switch statement:

switch(col.key) {
 case "name":
  col.val = fake.name();
  break;
 case "address":
  col.val = fake.address();
  break;
 ...
 default:
  throw new InvalidDataException();

As of version 3.10, Python added something similar: P634 - Structural Pattern Matching.

match subject:
    case <pattern_1>:
        <action_1>
    case <pattern_2>:
        <action_2>
    case <pattern_3>:
        <action_3>
    case _:
        <action_wildcard>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.