honey the codewitch Ответов: 2

Группы товаров с общим префиксом


итак, у меня есть эти (как структурированные данные)

тест -> expr
expr -> ambig1 ambig2 ambig3
expr -> ambig1 ambig2 ambig4
expr -> ambig1 ambig2
expr2 -> ambig2 ambig3
expr2 -> ambig2

вот что мне нужно

тест -> expr

expr -> ambig1 ambig2 ambig3
expr -> ambig1 ambig2 ambig4
expr -> ambig1 ambig2

expr2 -> ambig2 ambig3
expr2 -> ambig2


где каждый раздел находится в своем собственном контейнере (массив/словарь что угодно)

у меня есть идеи но их трудно реализовать и я не уверен что они сработают

У меня уже есть метод GetCommonPrefix

Я приму ответы в любом коде, на любом языке - но без LINQ

Эти структуры данных могут быть любыми. Массивы, строки, что угодно. Общий алгоритм будет тем же самым, даже если детали различны.

Что я уже пробовал:

Я перепробовал несколько вещей. Ни один не сработал. Вставка кода сюда заняла бы слишком много места.

CHill60

Что вы подразумеваете под "структурированными данными"? Это строки, объекты, списки или что-то еще?
Здесь недостаточно даже для того, чтобы начать помогать вам

honey the codewitch

вы можете рассматривать их как строки для целей данного вопроса.

но они являются массивами системы.Объект - где объект обычно является строкой. Рассматривайте объекты как сравнимые с равными

Рассмотрим левую часть a -> как первый элемент, если это поможет

Проблема не зависит от того, являются ли они массивами или строками, алгоритм будет одинаковым в любом случае.

2 Ответов

Рейтинг:
19

megaadam

Вставьте и запустите код здесь:
https://www.onlinegdb.com/online_python_interpreter[^]

Я бы не сказал, что это очень трудно.

lines = [   "test -> expr",
            "expr -> ambig1 ambig2 ambig3",
            "expr -> ambig1 ambig2 ambig4",
            "expr -> ambig1 ambig2",
            "expr2 -> ambig2 ambig3", 
            "expr2 -> ambig2"]

def get_matcher(s):
    return s[:s.find("->")+2]
    
def group_data(lines):
    groups = []
    new_group = []
    matcher = get_matcher(lines[0])
    for line in lines:
        if line.startswith(matcher):
            new_group.append(line)
        else:
            groups.append(new_group)
            new_group = [line]
            matcher = get_matcher(line)
            
    groups.append(new_group)
    return groups    
    
print(group_data(lines))


megaadam

Вышеизложенное предполагает, что данные "упорядочены", как и предоставленные вами данные.

Если он неупорядочен например:
русло = [
"тест -> expr",
"expr -> ambig1 ambig2 ambig3",
"тест -> ambig1 ambig2 ambig4",

Тогда лучше сделать словарь [Python] или карту [C++], Где ключи-это "matcher", а значения - "lines". Так что вместо составления списка списков это будет словарь списков

honey the codewitch

да, я использую словарь в своем коде, но все равно спасибо за предупреждение. Я в основном адаптирую то, что вы решили, чтобы посмотреть, работает ли это. Это выглядит слишком просто. Я почти уверен, что решение будет рекурсивным или, по крайней мере, использовать вложенные циклы, но, возможно, я ошибаюсь. Если вам интересно, это часть более крупной проблемы, называемой left factoring LL grammars

https://www.tutorialspoint.com/compiler_design/left_factoring.asp

megaadam

Ну, я бы подумал, что если ваши данные рекурсивны (то есть если элементы "ambig" содержат новые списки выражений "L -> R"), то код может быть рекурсивным или, по крайней мере, синтаксический анализатор должен построить рекурсивную структуру данных.

honey the codewitch

Я не думаю, что хорошо объясняю свои действия. Я имею в виду рекурсивный метод точно так же, как и метод sort (). рекурсивные сравнения, а не сравнения по рекурсивной структуре данных, если это имеет смысл.

кроме того, можно сделать эти вещи рекурсивными.

выражение -&ГТ; термин, выражение

honey the codewitch

А-А, и я ее разгадал. Конечно же, требовался внутренний цикл (можно было бы сделать рекурсивно)

Это как-то связано. Ваше решение не совсем сработало, но почти сработало. Во всяком случае, я использую в нем вариацию этой концепции

Рейтинг:
1

F-ES Sitecore

Я склонен реализовывать это следующим образом

Create dictionary collection to store results with string as key, list of string as value
For each string
    Get prefix
    If dictionary contains prefix as a key
        Retrieve value from dictionary and add result to it
    Else
        Add new item to dictionary with prefix as key and result in value collection
Loop


honey the codewitch

но как я узнаю, что такое префикс, если нет других элементов для его сравнения?

например, в

expr -> ambig2 ambig3

является ли префикс expr->ambig2 или expr-> ambig2 ambig3

беда в том, что я знаю префикс только тогда, когда сравниваю его с другими предметами.

F-ES Sitecore

В этом случае было бы лучше просто хранить данные в древовидной структуре с каждым элементом в виде узла. Аналогично вышеприведенному алгоритму вы разделите элемент на его части, затем для каждой части найдите узел в дереве и, если он не существует, добавьте его, а затем переместите вниз уровень для каждого элемента. Таким образом, вы получите что-то вроде

тест
-- выражение
выражение
-- амбиг1
---- амбиг2
------ амбиг3
------ амбиг4
и т.д.

вы можете сохранить исходные данные в виде значения каждого узла, и в конце процесса у вас будет представление данных, вложенных по префиксу.

honey the codewitch

может быть, у тебя там что-то и есть, но я должен все обдумать. Кофе Моар. =) Спасибо.