0
(defaultdict(None, {0: [((u'blood', u'test'), (2148, 'lab'), (1, 2), ''), ((u'crocin',), (u'47444.0', 'med'), (0,), '')], 1: [((u'back', u'pain'), (98, 'hc'), (0, 1), '')]}), [u'crocin blood test', u'back pain'], ['crocin blood test', 'back pain'])

I want to iterate over this dictionary and access just the tuples that contain the number,string pair like 2148,lab and 47444.0,med and 98,hc how to i run a loop to access these items ? The number of these items can be variable . I have a function that converts the input "crocin blood test. back pain" to the above dictionary.

yatu
  • 86,083
  • 12
  • 84
  • 139
  • Maybe use the [`filter`](https://docs.python.org/3/library/functions.html#filter) function while iterating over the [values](https://docs.python.org/3/library/stdtypes.html#dict.values). When constructing that dictionary, maybe also construct a separate container with the stuff you want to iterate over. – wwii Jun 20 '19 at 13:59
  • "The number of these items can be variable" - are you saying the number, string pairs might have a third element which you want to access? Or are they always strictly number, string. What about string, number? – GordonAitchJay Jun 20 '19 at 14:01
  • The tuple would always contain a number-string pair however in the above example there are 3 such pairs so by variable i mean the number of these pairs can be variable @GordonAitchJay – Divyansh Raj Jun 20 '19 at 14:05
  • What do you mean access? You want a loop that will return all the (number, string) tuples? – Lucas Wieloch Jun 20 '19 at 14:08
  • 1
    It would be easier to answer this question if you would clean up the data a bit. E.g., why are some numbers stored as integers and others as strings? Why are there other odd changes in data type across these tuples? It looks like any solution here is going to have to run a lot of annoying checks within the comprehension/loop/etc. that shouldn't need to be there, and questions around the nature of those checks are making it hard to tell what you really need here. – Atlas Jun 20 '19 at 14:19
  • @LucasWieloch yes, that is exactly what i want – Divyansh Raj Jun 20 '19 at 14:21
  • I agree with @Atlas, also, I'd like to add that if you research a bit more about this problem you'll figure it out. You can try looking at [similar problems][https://stackoverflow.com/questions/11004838/pattern-matching-tuples-and-multiplication-in-python] and making it work on your problem – Lucas Wieloch Jun 20 '19 at 14:35
  • Related: [How to make a flat list out of list of lists](https://stackoverflow.com/questions/952914/how-to-make-a-flat-list-out-of-list-of-lists) – wwii Jun 20 '19 at 15:07

1 Answers1

0

Is this what you are after?

dd = defaultdict(None, {0: [((u'blood', u'test'), (2148, 'lab'), (1, 2), ''), ((u'crocin',), (u'47444.0', 'med'), (0,), '')], 
                        1: [((u'back', u'pain'), (98, 'hc'), (0, 1), '')]})

for list_of_tuples in dd.values():
    for tuples in list_of_tuples:
        for tup in tuples:
            if len(tup) == 2:
                # Check if the 1st tuple element is a string
                if type(tup[1]) is not str:
                    continue

                # Check if the 0th tuple element is a number
                if type(tup[0]) is int:
                    is_number = True
                else:
                    try:
                        float(tup[0])
                        is_number = True
                    except ValueError:
                        is_number = False
                if is_number:
                    print("number-string pair found:", tup)

Output:

number-string pair found: (2148, 'lab')
number-string pair found: ('47444.0', 'med')
number-string pair found: (98, 'hc')

Because some of the numbers are actually stored and strings, you've got to check if they are valid numbers with int and float.


Refactored to clean up the logic:

for list_of_tuples in dd.values():
    for tuples in list_of_tuples:
        for tup in tuples:
            if len(tup) == 2 and isinstance(tup[1], str):
                try:
                    _ = float(tup[0])
                    print("number-string pair found:", tup)
                except ValueError:
                    pass

Actually, and isinstance(tup[1], str) in the conditional statement is probably not needed.


A generator that can be iterated:

def f(d):
    for list_of_tuples in dd.values():
        for tuples in list_of_tuples:
            for tup in tuples:
                if len(tup) == 2 and isinstance(tup[1], str):
                    try:
                        _ = float(tup[0])
                        yield tup
                    except ValueError:
                        pass

for thing in f(dd):
    print(thing)
GordonAitchJay
  • 4,640
  • 1
  • 14
  • 16
  • You should be able to simplify the logic/flow control by trying `float(tup[0])` first which will *work* for integers, floats and strings like `1234` - only one `try/except` and making `if type(tup[0]) is int` unnecessary. – wwii Jun 20 '19 at 15:00
  • Using [`isinstance`](https://docs.python.org/3/library/functions.html#isinstance) is preferred for checking object types. – wwii Jun 20 '19 at 15:01
  • The changes look great! Two questions: 1) why the _? It's not like we're unpacking a tuple and ignoring an element. Or is it simply for clarity - to show others we meant to ignore the result, and not that we accidentally didn't assign it to a variable? 2) I [think I] know the difference between "isinstance" and "type() is", but in this case, what is the benefit of isinstance? Thanks! – GordonAitchJay Jun 20 '19 at 15:38
  • When you see something assigned to `_` it is reasonable to assume it is not going to be used, it is a convention - [What is the purpose of the single underscore “_” variable in Python?](https://stackoverflow.com/questions/5893163/what-is-the-purpose-of-the-single-underscore-variable-in-python) – wwii Jun 20 '19 at 15:50
  • [From the docs](https://docs.python.org/3/library/functions.html#type): `The isinstance() built-in function is recommended for testing the type of an object, because it takes subclasses into account.` ... Also, [What are the differences between type() and isinstance()?](https://stackoverflow.com/questions/1549801/what-are-the-differences-between-type-and-isinstance) (many more if you search) – wwii Jun 20 '19 at 15:55
  • Sweet, I'll use isinstance and _ in similar situations. Thanks again! – GordonAitchJay Jun 20 '19 at 15:59