Edit: Это относится к более старой версии ОП, которая неясна в поиске последовательности в порядке; и поэтому это ищет последовательности по порядку, что сейчас неверно.
Существует много вариантов. Ниже я описываю один подход, который сначала маркерные строки, так и другой, который использует простое регулярное выражение, генерируемое из входной строки.
Подход 1: Синтаксические Струны
Начните с разбором каждого String
в массив подстрок, который сделает все эти легче работать. Вы можете разобрать каждую из строк, когда вы изначально читали их вместо каждый раз, когда вам нужно:
String myString = "A-B-C-D";
String[] sequence = myString.split("-");
Далее, рассмотреть возможность использования List<String>
вместо String[]
, потому что это сделает остальную часть этого немного проще (вы увидите). Таким образом, вместо того выше:
String myString = "A-B-C-D";
List<String> sequence = Arrays.asList(myString.split("-"));
Теперь проблема становится проверка, если два из этих массивов матча:
public static boolean containsSequence (List<String> searchIn, List<String> searchFor) {
}
Вы должны проверить оба направления, но вы можете просто повернуть вспять массив и уменьшить это проблема в дальнейшем просто проверяя направление вперед (есть, конечно, способы сделать это и избежать копии, но они могут быть сложными, и это только стоит, если у вас высокие требования к производительности):
public static boolean containsSequence (List<String> searchIn, List<String> searchFor) {
// first check forward
if (containsSequenceForward(searchIn, searchFor))
return true;
// now check in reverse
List<String> reversedSearchFor = new ArrayList<String>(searchFor);
Collections.reverse(reversedSearchFor);
return containsSequenceForward(searchIn, reversedSearchFor);
}
public static boolean containsSequenceForward (List<String> searchIn, List<String> searchFor) {
}
// usage example:
public static void example() {
List<String> searchIn = Arrays.asList("D-A-B-C".split("-"));
List<String> searchFor = Arrays.asList("A-C".split("-"));
boolean contained = containsSequence(searchIn, searchFor);
}
Теперь вам нужно всего лишь реализовать containsSequenceForward
. Я бы хотел, чтобы вы сделали это самостоятельно, но я предоставлю алгоритм в качестве подсказки:
- Начало в начале поискаВидео.
- Пройдите поиск по одному элементу за раз.
- Когда вы найдете текущий элемент searchFor в searchIn, продвигайте поискДля следующего элемента.
- Если вы попали в конец поиска, вы нашли последовательность.
- Если вы попали в конец поиска, но не искали, то последовательность не соответствует.
Теперь у вас есть возможность проверить, содержит ли одна последовательность другую в любом порядке. Чтобы применить его ко всей вашей коллекции, я рекомендую подготовить все строки в List<String>
один раз в начале, тогда вы можете пройти через каждый из них, используя вышеприведенный алгоритм.
Есть много альтернативных вариантов. Например, вы можете использовать indexOf
по адресу searchIn
, чтобы найти каждый элемент в searchFor
и убедиться, что индексы в порядке возрастания.
подход 2: Регулярные выражения
Другим вариантом здесь является использование регулярных выражений, чтобы найти последовательность поиска в исходной строке. Вы можете построить регулярное выражение динамически из последовательности поиска довольно легко:
String searchIn = "D-C-B-A";
String searchFor = "C-A";
String searchForPattern = searchFor.replace("-", ".*"); // yields "C.*A"
if (searchIn.matches(".*" + searchForPattern + ".*"))
/* then it matches forwards */;
Тогда матч в обратном направлении, если вперед матч не удается, вы можете просто обратный searchFor
и повторить:
String searchForReverse = new StringBuilder(searchFor).reverse().toString();
String searchForReversePattern = searchForReverse.replace("-", ".*"); // yields "A.*C"
if (searchIn.matches(".*" + searchForReversePattern + ".*"))
/* then it matches backwards */;
Обратите внимание, что это конкретное регулярное решение предполагает, что каждый элемент имеет длину всего один символ.
Также оба вышеуказанных подхода предполагают совпадение с регистром - чтобы сделать первый регистр без учета регистра, я бы просто преобразовал строки в нижний регистр перед разбором. Для второго вы можете использовать регулярное выражение без регистров.
Надеюсь, что это поможет. Поработайте на листе бумаги, если вам нужно.
Общая точка входа в исходное положение здесь помогает уменьшить эти проблемы до самых маленьких компонентов.
Если я правильно понял вопрос, вы можете просто разбить каждый символ, используя разделитель '-', а затем прокрутить их и посмотреть, содержит ли каждая строка в наборе строк все символы. –
Я попробую ваше предложение – DevfaR
@DevfaR: Пожалуйста, уточните, хотите ли вы * только * искать двухсимвольные строки, такие как «A-C», или если вы будете искать более длинные строки, такие как «A-D-B». Это источник многих предположений ниже. Если вы ищете только двухсимвольные строки, достаточно просто увидеть, содержит ли входная строка оба символа, независимо от того, имеет ли значение обратное значение. Однако, если вы ищете более длинные строки, тогда требуется другой алгоритм, который обеспечивает порядок поиска. –