Pao
Pao

Reputation: 3

I am confuse about this code can someone explain

Changing Duplicate characters in a string to ) and non duplicate to (.

I have tried 2 for loops but it doesn't work. I am beginner in coding therefore I cant understand this complex code can someone explain.

def duplicate_encode(word):
    return (lambda w: ''.join(('(', ')')[c in w[:i] + w[i+1:]] for i, c in enumerate(w)))(word.lower())

print(duplicate_encode("rEcede"))

Input: "Mercedes Bench"
Output: ()())()((()()(

Upvotes: 0

Views: 115

Answers (2)

gustible
gustible

Reputation: 11

This code replicates exactly what the lambda function does. By separating the logic into distinct statements it is easier to follow the logic. Remove the comments from the print statements to see the whole process in detail.

def simple_duplicate_encode(word):
    output = ""
    for i, c in enumerate(word):
        # print(i,c)
        i1 = word[:i]
        i2 = word[i+1:]
        # print(":{} = {}".format(i, word[:i]))
        # print("{}: = {}".format(i+1, word[i+1:]))
        is_duplicated = c in i1 + i2  #  Check to see if the character c is in the rest of the string
        # print("Is duplicated:{}".format(is_duplicated))
        character = ('(',')')[is_duplicated]  # If is_duplicated = True the value is 1, else 0
        # print(character)
        output += character
    return output

Upvotes: 0

gstukelj
gstukelj

Reputation: 2551

As said in a comment, I think this is bad coding practice and should be avoided. But it can serve as an example of code reading. So I'll give it a try here. (First you should read about lambda if you're not familiar with it.)

First, look at the matching parentheses and try to find the "deepest" parts:

  1. The top one is: lambda w: ''.join(('(', ')')[c in w[:i] + w[i+1:]] for i, c in enumerate(w))) applied to word.lower().

  2. Then we have ('(', ')')[c in w[:i] + w[i+1:]] for i, c in enumerate(w)) in place of three dots inside ''.join(...).

  3. enumerate(w), where w is a string, will produce an enumerate object that can be iterated to get tuples of form (i,c), where i is the index of the letter c. Try running for x in enumerate(w): print(x) for different strings w in order to get a feel for it.

  4. The ('(', ')')[c in w[:i] + w[i+1:]] for i, c in enumerate(w)) will then produce a generator object by iterating through the tuples of letters of w and the respective indices that will consist of only ')' and '(' that will be then concatenated by ''.join(...) into the final output string. Let's break it down further.

  5. [c in w[:i] + w[i+1:]] will always evaluate to either [True] or [False] (see 6 as to why). Now, ('(', ')')[False] will return '(' and ('(', ')')[True] will return ')' (something I learned right now by typing it out to see what happens).

  6. For any letter in w there will be a tuple in the generator object (see point 4), (i, c). The [c in w[:i] + w[i+1:]] will first take two substrings of w. The first one will include all the letters up to the position i (where the current letter is located) and the second will include all the letters after the current letter. These two substrings are then concatenated. Then c in part will just check if the current letter is in the resulting string, effectively checking if the letter c appears at some other part of the string as well. For example for a w = 'aba' and second tuple from enumerate('aba'), that is (1, 'b'), w[:i] will be equal to 'aba'[:1] which is 'a' and w[i+1:] will be equal to 'aba'[:1] which is equal to 'a', concatenated we get a string 'aa' and thus [c in w[:i] + w[i+1:]] which in this case is equal to ['b' in 'aa'] will evaluate to [False], hence resulting in '('.

Effectively the lambda part is just a function that for each letter at a given position, checks if the same letter is present in a modified string with the letter removed from that position. It is then applied to an argument word.lower() which just insures that the caps are ignored (e.g., 'A' and 'a' are counted as the same letter).

Upvotes: 1

Related Questions