Python — разделите строку с несколькими разделителями, верните разделитель словаря в качестве ключевого оставшегося элемента в качестве значения

#python #dictionary #split

#python #словарь #разделить

Вопрос:

Итак, я хотел знать, есть ли что-то, что принимает строку, разбивает ее на несколько разделителей, но вместо возврата списка он возвращает словарь того, какой разделитель использовался для разделения строки, за которым следует неразрывная строка до следующего разделителя. Например, рассмотрим этот список:

 Food to make:

1. Cake
    a. eggs
    b. flour
    c. milk
    d. etc
2. Salad
    a. lettuce
    b. spinach
    c. cheese
    d. ham
    e. etc
 

Вот неформатированный список:

 GroceryList = "1. Cake a. eggs b. flour c. milk d. etc 2. Salad a. lettuce b. spinach c. cheese d. ham e. etc"
 

Когда я запускаю свой скрипт, мне нужно, чтобы он разделялся по буквенно-цифровым значениям (и периоду), а затем возвращал его как словарь. В идеале я хотел бы иметь возможность устанавливать разделители с помощью списка ( my_str = "123test123" my_str.split(["1", "3"]) чтобы разделить строку по значениям «1» и «3», возвращая dict of {"1#1": "2", "3#1": "test", "1#2": "2", "3#2": ""} ). Я понимаю, что любые повторы будут перезаписаны в словаре, поэтому с ним должен быть связан уникальный идентификатор, например:

 {"#1": "Food to make:",
"1.#1": "Cake",
"a.#1": "eggs",
"b.#1": "flour",
"c.#1": "milk",
"d.#1": "etc",
"2.#2": "Salad",
"a.#2": "lettuce",
"b.#2": "spinach",
"c.#2": "cheese",
"d.#2": "ham",
"e.#2": "etc"}
 

Я бы не подумал, что для этого будет встроенная функция, но, видя, что я не очень хорошо знаком с python (я использую python 3.8), я решил, что задаю вопрос. выстрел.

Я рассмотрел функции сопоставления и лямбда-функции в качестве альтернативы, чтобы попытаться достичь этой цели, но я бы не знал, с чего даже начать решать подобную проблему, поэтому, если есть что-то родное для выполнения этой задачи, то это было бы лучше всего.

Спасибо!

—Редактировать—

Вот пример ввода, с которым я на самом деле буду иметь дело:

 M 10 315
L 110 215
A 30 50 0 0 1 162.55 162.45
L 172.55 152.45
A 30 50 -45 0 1 215.1 109.9
L 315 10
 

Комментарии:

1. является ли ваш входной «список» текстовым файлом или чем-то еще?

2. Можете ли вы опубликовать свой точный ввод в качестве переменной, которая может быть воспроизведена другими пользователями на их компьютерах?

3. Да, это строка, созданная из другого объекта

4. @AkshaySehgal попробуйте это… Я просто вижу оооочень много синтаксического анализа в моем будущем

5. Нет, это не то, что я имею в виду. В Food to make: 1. Cake a. eggs b. flour c. milk d. etc

Ответ №1:

Попробуйте это —

 import re
import string

alp = ' ' string.ascii_lowercase

#split by digits and then split by words
items = [re.split('w.',i) for i in re.split('d.', GroceryList)][1:]

#iterate over list of lists while keeping track of the index with enumerate
#then for the inner index return, return corresponding alphabet
#finally apply dict transformation
result = dict([(alp[l] '#' str(i),m.strip()) for i,j in enumerate(items,1) for l,m in enumerate(j)])
result
 
 {' #1': 'Cake',
 'a#1': 'eggs',
 'b#1': 'flour',
 'c#1': 'milk',
 'd#1': 'etc',
 ' #2': 'Salad',
 'a#2': 'lettuce',
 'b#2': 'spinach',
 'c#2': 'cheese',
 'd#2': 'ham',
 'e#2': 'etc'}
 

Комментарии:

1. 1. Просто хочу сказать, что я еще не тестировал это, но я уверен, что ценю помощь и (что я лично считаю) очень простое решение. 2. items отсутствует закрывающая скобка. 3. Результат не совсем то, к чему я стремлюсь, но это отличное начало. Я обновил свой вопрос (под неформатированной строкой), чтобы рассказать о том, как должна работать функция. 4. Это хорошее начало, я постараюсь это улучшить. Спасибо!

Ответ №2:

Использование:

  1. Сохраните класс как файл… Я назвал свой StringSplitter.py .
  2. import StringSplitter as SS
  3. ss = SS.StringSplitter("123test123", ["1", "3"])
  4. ss.split()
  5. ss.getSplit() или ss.toFile() для записи в файл с именем «split.txt «.

Который возвращает: [{'delimiter': '1', 'start': 0, 'end': 1, 'content': '2'}, {'delimiter': '3', 'start': 2, 'end': 3, 'content': 'testing'}, {'delimiter': '1', 'start': 10, 'end': 11, 'content': '2'}, {'delimiter': '3', 'start': 12, 'end': 13, 'content': ''}]

Когда вы восстанавливаете строку с помощью разделителя шаблона содержимого, это дает: 123testing123

 class StringSplitter:
    def __init__(self, string=None, delimeter=None, caseSensitive=True):
        self.string = string
        self.splitted = []
        self.delimeter = delimeter
        self.caseSensitive = caseSensitive

    def getSplit(self):
        return self.splitted

    def toFile(self):
        with open("./split.txt", "w") as file:
            file.writelines(str(self.splitted))

    def split(self):
        i = 0
        delCount = len(self.delimeter)
        strLen = len(self.string)
        split = []

        #loop through all chars in string
        while i < strLen:
            j = 0
            #loop over all possible delimiters
            while j < delCount:
                #get the delimiters
                searchitem = self.delimeter[j]
                compChar = self.string[i]
                if self.caseSensitive != True:
                    searchitem = searchitem.lower()
                    compChar = compChar.lower()
                #if the delimiter at its char 0 is the same as the string at i
                if searchitem[0] == compChar:
                    compItem = self.string[i:i   len(searchitem)]
                    if self.caseSensitive != True:
                        compItem = compItem.lower()
                    #check to see if the whole delimiter is matched at the rest of the string starting at i
                    if compItem == searchitem:
                        searchitem = self.string[i:i   len(searchitem)]
                        #then if there wasn't a match at the first character when a match was found,
                        #take the stuff up to the first match and make a dict out of it
                        #example: "string", ["i"] => [{"": "str"},{"i": "ng"}]
                        #for the purpose of this project, this is probably unnecessary
                        if len(split) == 0 and i > 0:
                            split.append({"delimiter": "", "start": 0, "end": i, "content": self.string[0: i]})
                            split.append({"delimiter": searchitem, "start": i, "end": i   len(searchitem), "content": ""})
                        else:
                            #add the delimiter and the starting and ending location of the of the delimeter
                            if len(split) > 0:
                                split[-1]["content"] = self.string[split[-1]["end"]: i]
                            split.append({"delimiter": searchitem, "start": i, "end": i   len(searchitem), "content": ""})
                        #break the loop
                        j = delCount   1
                        #if len(split) > 1:
                        #    split[-2]["content"] = self.string[int(split[-2]["end"]):int(split[-1]["start"])]
                    else:
                        #keep searching
                        j  = 1
                else:
                    #keep searching
                    j  = 1
            #keep searching
            i  = 1

        if len(split) > 1:
            split[-1]["content"] = self.string[int(split[-1]["end"]):]
        else:
            split[0]["content"] = self.string[int(split[0]["end"]):]
        self.splitted = split
 

Если кто-то этого хочет, я обновил его дальше, но не разместил здесь полный код. Пожалуйста, свяжитесь со мной, и мы сможем найти способ передачи кода. Он включает в себя несколько других методов для манипулирования строкой.

Комментарии:

1. @AkshaySehgal это то, к чему я стремлюсь. Это немного сомнительно по разным причинам, но это дает (насколько я могу судить) правильный результат.

2. @M-Chen-3 просто хотел ввести вас в цикл в соответствии с этим ответом.

3. Меня беспокоит эффективность… но это было лучшее, что я мог сделать.