2

Does python have util loop like in javascript? (eg. map, reduce and filter). Or everything must be done manually using for loop?

I have a simple 2 object records like below

json = [{
    "id": 1, "name": "a"
}, {
    "id": 2, "name": "b"
}]

How can I update name property if id is 2?

for index, x in json:
    if(x[id] == 2)
        //what to do here? change name to 'something'
4
  • map, reduce, filter, comprehensions Commented Jun 19, 2020 at 7:19
  • @deceze ah thanks, look like for loop is more readable than python's map Commented Jun 19, 2020 at 7:23
  • Python has no concise syntax for complex inline functions. Passing long-ish inline callbacks is a common idiom in Javascript, not so much in Python. In Javascript the standard for loop… isn't all that simple, that's why callbacks are more common. Python's for is perfectly simple and straight forward though. Commented Jun 19, 2020 at 7:24
  • js's for loop does the job but might need 2 variables else mutate the original variable which is a bad practice that's why map come to rescue. Commented Jun 19, 2020 at 7:30

6 Answers 6

3

The straight forward way:

for obj in json:
    if obj['id'] == 2:
        obj['name'] = 'something'

Objects are mutable, so you're directly mutating the object here. This is the simplest way. The typical Javascript equivalent would be:

json.forEach(obj => {
    if (obj.id == 2) {
        obj.name = 'something';
    }
});

The slightly more condensed version:

for obj in (o for o in json if o['id'] == 2):
    obj['name'] = 'something'

This inlines a generator expression which pre-filters the objects to loop over. Alternatively:

for obj in filter(lambda o: o['id'] == 2, json):
    obj['name'] = 'something'

Somewhat equivalent to:

json.filter(o => o.id == 2).forEach(obj => obj.name = 'something')

The even more condensed version:

json = [{**obj, 'name': 'something' if obj['id'] == 2 else obj['name']} for obj in json]

This is a list comprehension which builds a new object and new list, somewhat equivalent to:

json = json.map(o => ({...obj, name: obj.id == 2 ? 'something' : obj.name}))

You decide what you find most readable…

Sign up to request clarification or add additional context in comments.

4 Comments

thanks for the js reference! any resources for a js dev to best learn python? that will cut short my time to pick this new langguage.
🤷‍♂️ I don't know… Learn Python on its own merits, just make sure you read a lot of pythonic code to get how things are done. Don't try to port Javascript idioms over.
ah I see. I thought knowledge js will help.
Sure, general programming knowledge helps, but you'll find that details like this differ by languages.
2

Since your json is a list of dicts, you can loop through the dicts while checking your required condition:

json = [{
    "id": 1, "name": "a"
}, {
    "id": 2, "name": "b"
}]

for obj in json:
  if obj["id"] == 2:
    obj["name"] = 'something'

Result:

[{'id': 1, 'name': 'a'}, {'id': 2, 'name': 'something'}]

3 Comments

You may want to add break after the assignment.
There might be other dicts with 'id':2 so it depends on the use-case
why use break? meaning if there's another 2, python will change all the value to 'something'?
1

(That's a list of dictionaries, not a JSON string.)

The most concise (you can argue about readability) way I can think of is:

>>> [{**d, 'name': 'something' if d['id'] == 2 else d['name']} for d in json]
[{'id': 1, 'name': 'a'}, {'id': 2, 'name': 'something'}]

This builds a new list of dicts (not an inplace operation), so you would have to reassign the name json.

edit: fixed error from misreading the question.

2 Comments

js's map is readable but I think python doesn't 'care' about mutability so basic loop does the job. am I correct?
@AndreThonas you asked for something other than a for loop. The for loop is the straight forward answer. I don't know what you mean by "python doesn't 'care' about mutability" because it certainly does.
0

The syntax in your question is very closed, here are two working versions.

Option 1 use enumerate

If you prefer to access json by index, enumerate is what you are looking for:

for i, x in enumerate(json):
    if x['id'] == 2:
        json[i]['name'] = 'something'

print(json) # what you want

Option 2 directly modify x

From your example, you actually don't need the index i. You can directly modify x to achieve this. The reason is that when iterating a list through for x in, x is a reference to the original item in the list, not a copy, so any modification to x will be reflected in the original list.

for x in json:
    if x['id'] == 2:
        x['name'] = 'something'

print(json) # what you want

Comments

0

Yes, Python has map and friends, see https://docs.python.org/3/library/functions.html .

As others stated, it's more pythonic to just use for loops. But if you want to use (and abuse) functional programming style, you can do it as:

any(map(lambda item: (item['id'] == 2) and item.update(name='something'), json))

The same with some comments:

any( # map will return an iterator, any is there to force the evaluation on each element
    map(
         lambda item:          # function to be applied
             (item['id'] == 2) # our condition
             and               # 'and' is lazy evaluated, if 'id' != 2
                               # we don't evaluate the following line
             item.update(      # update item with another dict
                 name = 'something' # use the fact that keyword arguments are given as a dict
             ), # the return value will always be false
                # forcing 'any' to look further
         json                  # the list we apply the map to
       )
   )

3 Comments

That seriously is snake abuse… ಠ_ಠ
what does it means? sounds funny haha.
@AndreThonas I added comments for you
-1

Python have all these functions like map, reduce, and filter. Please refer https://www.learnpython.org/en/Map,_Filter,_Reduce

You also can use the list comprehension feature which is quite useful and handy. Here I have written the list_comprehension for getting the list of specified condition which is id is 2 here.

output_list = [i.get("name") for i in json if i.get("id") == 2]

expected output

['b']

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.