-1

I have a list of over 50 elements. These elements are lowercase and uppercase alphabets, numbers, special characters.

eg.

sample_list = ['1', '0', 'b', 'B', '2', '6', 'a', '7', '9', '5', 'c', 'd', '4', 'A', 'C', 'f', 'D', 'F', '3', 'C', '8', 'A', 'F', 'B', 'A', 'A', 'D'] 

I want to interchange particular elements with a special character. eg.

replacing `A,B,C and 1 with @
replacing `D,E,F and 2 with &
replacing `G,H,I and 3 with (

and so on, I have to replace a particular set of elements with 11 selected special characters. Like I replaced few selected elements with 3 of the special characters.

How to do it efficiently.

Cool Breeze
  • 738
  • 2
  • 10
  • 26
  • 1
    Why are ppl always ask how to do it "efficiently" ? How did you try to solve it? What was your bottleneck? What was your problem? Where is your [mcve]? – Patrick Artner Feb 16 '19 at 14:35
  • @PatrickArtner , I had created many lists and then was searching which list the element belongs and then replacing it with the resp special character. It wasn't efficient. – Cool Breeze Feb 16 '19 at 14:48

5 Answers5

5

You could do it using translate method following way:

sample_list = ['1', '0', 'b', 'B', '2', '6', 'a', '7', '9', '5', 'c', 'd', '4', 'A', 'C', 'f', 'D', 'F', '3', 'C', '8', 'A', 'F', 'B', 'A', 'A', 'D']
t = ''.maketrans('ABC1DEF2GHI3','@@@@&&&&((((')
out = [i.translate(t) for i in sample_list]
print(out)

Output:

['@', '0', 'b', '@', '&', '6', 'a', '7', '9', '5', 'c', 'd', '4', '@', '@', 'f', '&', '&', '(', '@', '8', '@', '&', '@', '@', '@', '&']

maketrans method of str is used for creating translation table, just feed it with two equal length strs with first consisting of keys and second of values. translate method accept that table and replace characters accordingly, or left original intact if that there is not such key in table.

EDIT: As noted by Olivier Melançon it can be used only if you want to replace 1 character with 1 character.

Daweo
  • 31,313
  • 3
  • 12
  • 25
  • It's neat, although it's good to point out that this method will not be able to extend to a sample list with elements of more than one character. – Olivier Melançon Feb 16 '19 at 14:35
1

You first need to define your replacement rules, by example with a dict. In particular, since dict allows O(1) access, this is as fast as your method will be able to get time-complexity-wise: that is solve it in a single traversal of the list.

You can then traverse the list and replace each element if it has a replacement rule.

rules = {
    'A': '@',
    'B': '@',
    'D': '&',
    'E': '&'
}

for i, c in enumerate(sample_list):
    if c in rules:
        sample_list[i] = rules[c]

If you wish to create a new list instead of mutating the initial one, you can use a list-comprehension

new_list = [rules.get(c, c) for c in sample_list]

Example

rules = {
    'A': '@',
    'B': '@',
    'D': '&',
    'E': '&'
}

sample_list = ['A', 'A', 'B', 'C', 'D', 'E', 'F']

new_list = [rules.get(c, c) for c in sample_list]

print(new_list)

Output

['@', '@', '@', 'C', '&', '&', 'F']
Olivier Melançon
  • 21,584
  • 4
  • 41
  • 73
0

Try this and set all of your maping in dictionary:

chars = {"@": ["A", "B", "C", "1"], "&": ["D", "E", "F", "2"]}
sample_list = ['1', '0', 'b', 'B', '2', '6', 'a', '7', '9', '5', 'c', 'd', '4', 'A', 'C', 'f', 'D', 'F', '3', 'C', '8', 'A', 'F', 'B', 'A', 'A', 'D']

for k, v in chars.items():
    for value in v:
        if value in sample_list:
            ind = [index for index, val in enumerate(sample_list) if val == value]            
            for x in ind:
                sample_list[x] = k


print(sample_list)
Heyran.rs
  • 501
  • 1
  • 10
  • 20
0

You can use the map function:

Ex for the first replacement:

new_list = map(lambda x: '@' if x in ('A', 'B', 'C') else x, sample_list)

sample_list can be a string too (each character is one element, but map will return an array either way).

On a "string" list, you could just use the replace method:

compact_list = ''.join(sample_list)
new_compact_list = compact_list.replace('A', '@').replace('B', '@').replace('C', '@')

Of course if the source list is variable, write a loop around it...

Thomas Guyot-Sionnest
  • 2,251
  • 22
  • 17
0

Start with a simple function and refine it.

Simple would be using 3 sets (for lookup set is better then lists) - if sets do not need to mutate, use frozensets instead. Use a simple loop - straight forward:

sample_list = ['1', '0', 'b', 'B', '2', '6', 'a', '7', '9', '5', 'c', 'd', '4', 'A', 'C', 'f', 'D', 'F', '3', 'C', '8', 'A', 'F', 'B', 'A', 'A', 'D'] 

new_list = []
for item in sample_list:
    abc = frozenset("ABC")    # frozensets do not change, they are immuteable
    dfe = frozenset("DEF")    # and fast for lookups. this is less performant
    ghi = frozenset("GHI")    # then using a dict - but it works as well

    if item in abc:
        new_list.append("@")
    elif item in dfe:
        new_list.append("&")
    elif item in ghi:
        new_list.append("(")
    else:
        new_list.append(item)

print(new_list)

Output:

['1', '0', 'b', '@', '2', '6', 'a', '7', '9', '5', 'c', 'd', '4', '@', '@', 'f', '&', '&', '3', '@', '8', '@', '&', '@', '@', '@', '&']

To get more fancy use a dictionary and list-comp:

transform = {"A":"@", "B":"@", "C":"@", 
             "D":"&", "E":"&", "F":"&", 
             "G":"(", "H":"(", "I":"("}

new_list = [ transform.get(i,i) for i in sample_list]

Output:

['1', '0', 'b', '@', '2', '6', 'a', '7', '9', '5', 'c', 'd', '4', '@', '@', 'f', '&', '&', '3', '@', '8', '@', '&', '@', '@', '@', '&']

See:

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69