Fügen Sie eine Zeichenfolge in die angegebene Zeichenfolge am angegebenen Index in Python ein

76

Ich bin ein Neuling in Python und habe ein Problem: Wie füge ich einige Felder in bereits vorhandene Zeichenfolgen ein?

Angenommen, ich habe eine Zeile aus einer Datei gelesen, die Folgendes enthält:

line = "Name Age Group Class Profession"

Jetzt muss ich das dritte Feld (Gruppe) dreimal mehr in dieselbe Zeile vor dem Klassenfeld einfügen. Dies bedeutet, dass die Ausgangsleitung wie folgt lauten sollte:

output_line = "Name Age Group Group Group Group Class Profession"

Ich kann das 3. Feld leicht abrufen (mit der splitMethode), aber bitte lassen Sie mich wissen, wie ich es am einfachsten in die Zeichenfolge einfügen kann.

James
quelle

Antworten:

138

Ein wichtiger Punkt, der neue Python-Programmierer oft beißt, aber die anderen Poster nicht explizit gemacht haben, ist, dass Zeichenfolgen in Python unveränderlich sind - Sie können sie niemals an Ort und Stelle ändern.

Sie müssen sich neu trainieren, wenn Sie mit Zeichenfolgen in Python arbeiten, damit Sie nicht überlegen: "Wie kann ich diese Zeichenfolge ändern?" Stattdessen denkst du: "Wie kann ich eine neue Saite erstellen, die einige Stücke von dieser enthält, die ich bereits bekommen habe?"

bgporter
quelle
36
Dies entschuldigt Python nicht wirklich dafür, dass es keine indizierte Einfügung oder Ersetzung gibt! Die Ausgabe kann nur eine neue Zeichenfolge sein, die das gewünschte Ergebnis enthält.
Codie CodeMonkey
8
@CodieCodeMonkey Der Python Zen erwähnt, dass "Explizit besser als implizit" ist. Sie möchten, dass der Entwickler weiß, dass er an einer Kopie arbeitet. Andernfalls wird er mit Sicherheit auf Probleme mit der Objektidentität stoßen, deren Debugging frustrierend sein wird. Thinking String - Denken Sie funktional.
Zakum
10
@Zakum, ich verstehe Ihren Standpunkt, aber es gibt Präzedenzfälle dafür, z. B. str.strip (). Ein Entwickler, der die Dokumentation nicht sorgfältig gelesen hat, könnte denken, dass strip () mit dem Original arbeitet.
Codie CodeMonkey
2
Dies beantwortete die Frage ohne eine einzige Codezeile. Die Kraft einer korrekten Denkweise.
Jchnxu
2
"how can I create a new string that has some pieces from this one I've already gotten?"Ok, aber wie ?
Det
120

Für zukünftige "Neulinge", die sich mit diesem Problem befassen, denke ich, dass eine schnelle Antwort zu diesem Thread passen würde.

Wie bgporter sagte: Python-Strings sind unveränderlich. Um einen String zu modifizieren, müssen Sie die bereits vorhandenen Teile verwenden.

Im folgende Beispiel füge ich 'Fu'bei 'Kong Panda', zu schaffen'Kong Fu Panda'

>>> line = 'Kong Panda'
>>> index = line.find('Panda')
>>> output_line = line[:index] + 'Fu ' + line[index:]
>>> output_line
'Kong Fu Panda'

Im obigen Beispiel habe ich den Indexwert verwendet, um die Zeichenfolge in zwei Teilzeichenfolgen zu unterteilen: 1 enthält die Teilzeichenfolge vor dem Einfügeindex und die andere enthält den Rest. Dann füge ich einfach die gewünschte Zeichenfolge zwischen den beiden und voilà hinzu, wir haben eine Zeichenfolge in eine andere eingefügt.

Pythons Slice-Notation hat eine großartige Antwort, die das Thema des String-Slicing erklärt.

Ben Avnon
quelle
39
Tolle Antwort, aber ich glaube, der Filmtitel lautet " Kung Fu Panda"
James Vickery
8
Tatsächlich sind sowohl "buchstabiert" als auch "buchstabiert" korrekt. "buchstabiert" ist die britische Schreibweise. "Dinkel" ist in Amerika nur inakzeptabel, weil "muh," Landwirtschaft "." Es variiert von Dialekt zu Dialekt, und "Dinkel" ist genauso alt wie "Dinkel". Ist es zum Beispiel "Axt eine Frage" oder "Frage stellen"? Die Antwort ist beides - beide sind jetzt fast zweitausend Jahre alt, und von den beiden glaube ich, dass "Axt" zuerst erscheint; "fragen" war einfach beliebter.
Matthew T. Scarbrough
1
Beachten Sie, dass find()der Startindex des ersten Vorkommens zurückgegeben wird und zurückgegeben wird, -1wenn die gesuchte Zeichenfolge nicht gefunden wird. Dies lässt sich also nicht auf Situationen verallgemeinern, in denen die interessierende Zeichenfolge in diesem Fall Pandamehrmals oder gar nicht auftreten kann.
tony_tiger
18

Ich weiß, dass es Malapropos ist, aber meiner Meinung nach ist der einfache Weg:

def insert (source_str, insert_str, pos):
    return source_str[:pos]+insert_str+source_str[pos:]
Sim Mak
quelle
2
Was ist Malapropos darüber
sehe
1
@sehe Es verwendet String-Verkettung, die nicht sehr effizient ist
Rob Smallshire
Danke, ich hatte gehofft, dass Sie der Antwort die Klarstellung hinzufügen. Nicht jeder würde den Nachteil verstehen, und es ist nützlich für die Leute zu wissen :)
sehe
@RobSmallshire Was wäre eine effizientere Methode?
Jacob Jones
@JacobJones Die Verwendung der Join-Methode von str wäre wahrscheinlich effizienter und vermeidet möglicherweise große Zwischenergebnisse. return '' .join ((source_str [: pos], insert_str, source_str [pos:]))
Rob Smallshire
7
line='Name Age Group Class Profession'
arr = line.split()
for i in range(3):
    arr.insert(2, arr[2])
print(' '.join(arr))
Michał Niklas
quelle
str.join () hat den Vorteil, dass die Speichernutzung reduziert wird, da keine Zwischenzeichenfolgen erstellt werden (obwohl IIRC dies in neueren Versionen von CPython / PyPy optimiert wurde). Auf der anderen Seite ist es langsamer als die Verkettung, wenn nur eine Handvoll Zeichenfolgen kombiniert werden, und daher am nützlichsten für den Umgang mit großen Zeichenfolgen oder wenn Sie sonst eine große Anzahl von Verkettungen durchführen müssten. Unter Python 3.6 können Sie anstelle der Verkettung f-Strings verwenden, um einige zusätzliche CPU-Zyklen zu speichern, wenn die Anzahl der Ersetzungen festgelegt ist (z. B. f '{source_str [: pos]} {insert_str} {source_str [pos:]}'). ).
Kgriffs
4

Es gibt verschiedene Möglichkeiten, dies zu tun:

Eine Möglichkeit ist das Schneiden:

>>> a="line=Name Age Group Class Profession"
>>> b=a.split()
>>> b[2:2]=[b[2]]*3
>>> b
['line=Name', 'Age', 'Group', 'Group', 'Group', 'Group', 'Class', 'Profession']
>>> a=" ".join(b)
>>> a
'line=Name Age Group Group Group Group Class Profession'

Eine andere Möglichkeit wäre, reguläre Ausdrücke zu verwenden:

>>> import re
>>> a=re.sub(r"(\S+\s+\S+\s+)(\S+\s+)(.*)", r"\1\2\2\2\2\3", a)
>>> a
'line=Name Age Group Group Group Group Class Profession'
Tim Pietzcker
quelle
4

Ich hatte ein ähnliches Problem bei meiner DNA-Zuordnung und habe den Rat von bgporter verwendet, um es zu beantworten. Hier ist meine Funktion, die einen neuen String erstellt ...

def insert_sequence(str1, str2, int):
    """ (str1, str2, int) -> str

    Return the DNA sequence obtained by inserting the 
    second DNA sequence into the first DNA sequence 
    at the given index.

    >>> insert_sequence('CCGG', 'AT', 2)
    CCATGG
    >>> insert_sequence('CCGG', 'AT', 3)
    CCGATG
    >>> insert_sequence('CCGG', 'AT', 4)
    CCGGAT
    >>> insert_sequence('CCGG', 'AT', 0)
    ATCCGG
    >>> insert_sequence('CCGGAATTGG', 'AT', 6)
    CCGGAAATTTGG

    """

    str1_split1 = str1[:int]
    str1_split2 = str1[int:]
    new_string = str1_split1 + str2 + str1_split2
    return new_string
Homam Bahrani
quelle
1

Implementierung

Mit den folgenden Funktionen kann eine Zeichenfolge in eine andere Zeichenfolge eingefügt werden:

def str_insert(from_me, into_me, at):
    """
    Inserts the string <from_me> into <into_me>

    Input <at> must be an integer index of <into_me> or a substring of <into_me>

    Inserts <from_me> AFTER <at>, not before <at>

    Inputs <from_me> and <into_me> must have working __str__ methods defined.
    This is satisfied if they already are strings.

    If not already strings, <from_me>, <into_me> are converted into strings.

    If you try to insert an empty string, that's fine, and the result
    is no different from the original.

    In order to insert 'from_me' after nothing (insert at the beginning of the string) use:
        at = ''  or  at = 0
    """
    try:
        return str_insert_or_raise(from_me, into_me, at)
    except ValueError as err:
        serr = str(err)
        if (str_insert_or_raise.__name__ in serr) and 'not found' in serr and '<at>' in serr:
            # if can't find where to insert stuff, don't bother to insert it
            # use str_insert_or_raise if you want an exception instead
            return into_me
        else:
            raise err

##############################################################

def str_insert_or_raise(from_me, into_me, at):
    """
    Inserts the string <from_me> into <into_me>

    Inserts <from_me> AFTER <at>, not before <at>

    Input <at> must be an integer index of <into_me> or a substring of <into_me>

    If <at> is the string '15', that substring will be searched for,
    '15' will not be interpreted as an index/subscript.        

    Inputs <from_me> and <into_me> must have working __str__ methods defined.
    If not already strings, <from_me>, <into_me> are converted into strings. 

    If you try to insert something, but we cannot find the position where
    you said to insert it, then an exception is thrown guaranteed to at least
    contain the following three substrings:
        str_insert_or_raise.__name__
        'not found'
        '<at>'
    """
    try:
        if isinstance(at, int):
            return str_insert_by_int(from_me, into_me, at)
        # Below, the calls to str() work fine if <at> and <from_me> are already strings
        # it makes them strings if they are not already
        return str_insert_by_str(str(from_me), str(into_me), str(at))
    except ValueError as err:
        serr = str(err)
        if 'empty string' in serr:
            return into_me # We allow insertion of the empty string
        elif ("<at>" in serr) and 'not found' in serr:
            msg_start = "In " + str_insert_or_raise.__name__ + ":  "
            msg = [msg_start, "\ninput ", "<at> string", " not found in ", "<into_me>",
                              "\ninput <",   str(at)  , "> not found in <", str(into_me), ">"]
            msg = ''.join(msg)
            raise ValueError(msg) from None
        else:
           raise err
#############################################################
def str_insert_by_str(from_me, into_me, at):
    """
    Inserts the string <from_me> into <into_me>

    puts 'from_me' AFTER 'at', not before 'at'
    For example,
        str_insert_or_raise(at = '2',  from_me = '0', into_me = '123')
    puts the zero after the 2, not before the 2
    The call returns '1203' not '1023'

    Throws exceptions if input arguments are not strings.

    Also, if <from_me> is empty or <at> is not a substring of <into_me> then
    an exception is raised.

    For fewer exceptions, use <str_insert_or_raise> instead.
    """
    try:
        s = into_me.replace(at, at + from_me, 1)
    except TypeError as terr: # inputs to replace are not strings
        msg_list = ['Inputs to function ', str_insert_by_str.__name__, '() must be strings']
        raise TypeError(''.join(msg_list)) from None
    # At the end of call to replace(), the '1'  indicates we will replace
    # the leftmost occurrence of <at>, instead of every occurrence of <at>
    if (s == into_me): # <at> string not found and/or <from_me> is the empty string
        msg_start = "In " + str_insert_by_str.__name__ + ":  "
        if from_me == '':
            msg = ''.join([msg_start, "attempted to insert an empty string"])
            raise ValueError(msg) from None
        raise ValueError(msg_start, "Input <at> string not found in <into_me>.",
                                    "\nUnable to determine where you want the substring inserted.") from None
    return s
##################################################
def str_insert_by_int(from_me, into_me, at):
    """
    * Inserts the string <from_me> into <into_me> at integer index <at>    
    * throws exceptions if input arguments are not strings.    
    * Also, throws an  exception if you try to insert the empty string    
    * If <at> is less than zero, <from_me> gets placed at the
      beginning of <into_me>    
    * If <at> is greater than the largest index of <into_me>,
      <from_me> gets placed after the end of <into_me>

    For fewer exceptions, use <str_insert_or_raise> instead.
    """
    at = into_me[:(at if at > 0 else 0)]
    return str_insert_by_str(from_me, into_me, at)

Verwendung

Der folgende Code zeigt, wie str_insertdie zuvor angegebene Funktion aufgerufen wird

def foo(*args):
    return args

F = 'F. '

s = 'Using the string \'John \' to specify where to make the insertion'
result = str_insert(from_me = F, into_me ='John Kennedy', at ='John ')
print(foo('\n\n', s, '\n', result))

s = 'Using an int returned by find(\'Ken\') to specify where to make the insertion'
index = 'John Kennedy'.find('Ken') # returns the position of the first letter of 'Ken', not the last letter
result = str_insert(from_me = F, into_me ='John Kennedy', at = index)
print(foo('\n\n', s, '\n', result))

s = 'Using an int (5) to specify where to make the insertion.'
result = str_insert(from_me = F, into_me ='John Kennedy', at = 5)
print(foo('\n\n', s, '\n', result))

s = "Looking for an 'at' string which does not exist"
result = str_insert(from_me = F, into_me ='John Kennedy', at ='x')
print(foo('\n\n', s, '\n', result))

s = ''.join(["Looking for the empty string.",
             "\nFind one immediately at the beginning of the string"])
result = str_insert(from_me = F, into_me ='John Kennedy', at = '')
print(foo('\n\n', s, '\n', result))

s = "Insert an empty string at index 3. No visible change"
result = str_insert(from_me = '', into_me = 'John Kennedy', at = 3)
print(foo('\n\n', s, '\n', result))    

for index in [-5, -1, 0, 1, 997, 999]:
    s = "index " + str(index)
    result = str_insert(from_me = F, into_me = 'John Kennedy', at = index)
    print(foo('\n\n', s, '\n', result))

Warnung vor mangelnder Möglichkeit, Änderungen an Ort und Stelle vorzunehmen

Keine der oben genannten Funktionen ändert eine Zeichenfolge "an Ort und Stelle". Die Funktionen geben jeweils eine geänderte Kopie der Zeichenfolge zurück, die ursprüngliche Zeichenfolge bleibt jedoch erhalten.

Zum Beispiel,

s = ''.join(["Below is what we get when we forget ",
             "to overwrite the string with the value",
             " returned by str_insert_or_raise:"])

examp_str = 'John Kennedy'
str_insert('John ', F, examp_str)
print(foo('\n\n', s, '\n', examp_str))

# examp_str is still 'John Kennedy' without the F
Zahnstocher Anemone
quelle
0

Antwort für Einfügen von Zeichenfolgen an anderen Positionen der Zeichenfolge

str1 = "ibuprofen"
str2 = "MEDICAL"
final_string=""
Value = 2
list2=[]
result=[str1[i:i+Value] for i in range(0, len(str1), Value)]
count = 0

for letter in result:
    if count < len(result)-1:
        final_string = letter + str2[count]
        list2.append(final_string)
    elif ((len(result)-1)==count):
        list2.append(letter + str2[count:len(str2)])
        break
    count += 1

print(''.join(list2))
Pavan Kumar
quelle
Hinweis: habe auf stackoverflow.com/questions/53168288/… geantwortet, da die Beantwortung dort deaktiviert und auf diese getäuscht wurde
pavan kumar