Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to skip enumeration by element types #53

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Minyus
Copy link

@Minyus Minyus commented Dec 27, 2021

flatten-dict enumerates all the lists if enumerate_types=(list,) regardless of the element types.

The modification by this Pull Request adds flexibility to enumerate based on the element types while keeping the backward compatibility.

For example, users can now keep list of specific data types (e.g. str) set by keep_element_types argument while still enumerating list of other types.

        >>> flatten({'a': ['b', 'c']}, enumerate_types=(list,), keep_element_types=(str,))
        {('a',): ['b', 'c']}

        >>> flatten({'a': [10, 11]}, enumerate_types=(list,), keep_element_types=(str,))
        {('a', 0): 10, ('a', 1): 11}

        >>> flatten({'a': [{'b': 'foo'}]}, enumerate_types=(list,), keep_element_types=(str,))
        {('a', 0, 'b'): 'foo'}

@ianlini ianlini self-requested a review December 28, 2021 07:37
and not (
keep_element_types
and isinstance(value, enumerate_types)
and any([isinstance(e, keep_element_types) for e in value])
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
and any([isinstance(e, keep_element_types) for e in value])
and any(isinstance(e, keep_element_types) for e in value)

@ianlini
Copy link
Owner

ianlini commented Dec 28, 2021

Thanks for your contribution. I'm thinking about a more general way to fulfill your requirement because keep_element_types looks too specific to some specific cases. I have 2 alternatives in my mind:

  1. Accept callable in enumerate_types and when checking the type, replace the if isinstance(value, enumerate_types) with something like if any(isinstance(value, t) if isinstance(t, type) else t(parent, value) for t in enumerate_types). Note that I use t(parent, _d) here because I think parent might be useful in some cases.

  2. Add a exclude_enumerate_types and accept the type representation in typing (e.g., List[str]), and use some third-party package to check the type. However, this might not solve all the issue. When there are int and str in the list, it won't be a List[str]. If you want to reject the enumeration in this case, it might be hard to represent that you want to check whether there is at least one str in the list.

@ianlini
Copy link
Owner

ianlini commented Dec 28, 2021

An example for the usage:

>>> flatten({'a': ['b', 'c']}, enumerate_types=(list,), keep_element_types=(str,))

is equivalent to

def is_list_of_nonstr(parent, obj):
    return isinstance(obj, list) and not any(isinstance(val, str) for val in obj)

flatten({'a': ['b', 'c']}, enumerate_types=(is_list_of_nonstr,))

@ianlini
Copy link
Owner

ianlini commented Dec 28, 2021

You can do more interesting things like this:

from some_type_checking_tool import check

def is_list_of_str(parent, obj):
    return check(obj, list[str])

def is_the_specific_key(parent, obj):
    return parent == ("the", "specific", "key")

@Minyus
Copy link
Author

Minyus commented Dec 28, 2021

Sure, sounds good to me. Could you please implement it?

@ianlini
Copy link
Owner

ianlini commented Dec 29, 2021

Will do it when I have time. Issue created: #54.
Thanks.

@Minyus
Copy link
Author

Minyus commented Dec 29, 2021

Thank you! I look forward to it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants