Home > Software engineering >  loop list of json strings and change element every N time
loop list of json strings and change element every N time

Time:08-21

I have a function that takes a list of json strings and replaces [link] with one item of a list of links, and I want to replace [link] with every N (variable) item of the list.

import itertools


ll = [
    {
        'Messages': [
            {'id': 'int', 'Text': 'string with [link] !'},
            {'id': 'int', 'Text': 'string with [link] !'},
        ]
    },
    {
        'Messages': [
            {'id': 'int', 'Text': 'string with [link] !'},
            {'id': 'int', 'Text': 'string with [link] !'},
        ]
    },
    {
        'Messages': [
            {'id': 'int', 'Text': 'string with [link] !'},
            {'id': 'int', 'Text': 'string with [link] !'},
        ]
    },
]

links = ['aaa', 'bbb', 'ccc']


def changer(ll):
    cy = itertools.cycle(links)
    for i in ll:
        ni = i.replace('[link]', next(cy))
        print(next(cy))
        print(type(ni))

For example, if N = 2 for every 2 items of the list cycle to the next link.

But my code replaces all with the first element of the list 'aaa' in this case.

The result should look like this:

N = 2

[
    {
        'Messages': [
            {'id': 'int', 'Text': 'string with aaa !'},
            {'id': 'int', 'Text': 'string with aaa !'},
        ]
    },
    {
        'Messages': [
            {'id': 'int', 'Text': 'string with aaa !'},
            {'id': 'int', 'Text': 'string with aaa !'},
        ]
    },
    {
        'Messages': [
            {'id': 'int', 'Text': 'string with bbb !'},
            {'id': 'int', 'Text': 'string with bbb !'},
        ]
    },
    {
        'Messages': [
            {'id': 'int', 'Text': 'string with bbb !'},
            {'id': 'int', 'Text': 'string with bbb !'},
        ]
    },
]

CodePudding user response:

Use a simple loop with zip:

for d1, l in zip(ll, links):
    for d2 in d1['Messages']:
        d2['Text'] = d2['Text'].replace('[link]', l)

modified ll:

[{'Messages': [{'id': 'int', 'Text': 'string with aaa !'},
               {'id': 'int', 'Text': 'string with aaa !'}]},
 {'Messages': [{'id': 'int', 'Text': 'string with bbb !'},
               {'id': 'int', 'Text': 'string with bbb !'}]},
 {'Messages': [{'id': 'int', 'Text': 'string with ccc !'},
               {'id': 'int', 'Text': 'string with ccc !'}]},
]

CodePudding user response:

You could use enumerate() to assign number to every item on list and run next(cy) only when number % N == 0


Working example.

I used more readable names for variables.

import itertools

data = [
    {
        'Messages': [
            {'id': 'int', 'Text': 'string with [link] !'},
            {'id': 'int', 'Text': 'string with [link] !'},
        ]
    },
    {
        'Messages': [
            {'id': 'int', 'Text': 'string with [link] !'},
            {'id': 'int', 'Text': 'string with [link] !'},
        ]
    },
    {
        'Messages': [
            {'id': 'int', 'Text': 'string with [link] !'},
            {'id': 'int', 'Text': 'string with [link] !'},
        ]
    },
]

links = ['aaa', 'bbb', 'ccc']

N = 2

links_cycle = itertools.cycle(links)

for number, item in enumerate(data):
    
    if number % N == 0:
        new_link = next(links_cycle)
        
    for message in item['Messages']:
        message['Text'] = message['Text'].replace('[link]', new_link)
        
    print(item)

Result:

{'Messages': [{'id': 'int', 'Text': 'string with aaa !'}, 
              {'id': 'int', 'Text': 'string with aaa !'}]}

{'Messages': [{'id': 'int', 'Text': 'string with aaa !'}, 
              {'id': 'int', 'Text': 'string with aaa !'}]}

{'Messages': [{'id': 'int', 'Text': 'string with bbb !'}, 
              {'id': 'int', 'Text': 'string with bbb !'}]}

BTW:

Other method: create list with repeated values

links = ['aaa', 'aaa', 'bbb', 'bbb', 'ccc', 'ccc']

which you can create using

links = [item for item in links for _ in range(N)]

and next run next() in every loop.

It can be useful when you would repeat some values different times

ie. aaa x 1 , bbb x 3 , ccc x 2

links = ['aaa', 'bbb', 'bbb', 'bbb', 'ccc', 'ccc']

which you caan create using

N = [1, 3, 2]
links = ['aaa', 'bbb', 'ccc']

links = [item for item, number in zip(links, N) for _ in range(number)]
  • Related