Как вы можете создать карту или список индексов позиции подстроки-Java?

#java #substring

#java #подстрока

Вопрос:

Я разбираю много строк из текстового файла. Строки файла имеют фиксированную длину, но в зависимости от начала строки, например «0301 ….», структура данных файла разделяется. есть пример строк, начинающийся с 11, 34 и т.д., И на основе этого строка разделяется по-разному.

Пример: если начало строки содержит «03», то строка будет разделена на

 name = line.substring(2, 10);
surname = line.substring(11, 21);
id = line.substring(22, 34);
adress = line.substring (35, 46); 
  

Другой пример: если начало строки содержит «24», то строка будет разделена на

 name = line.substring(5, 15);
salary = line.substring(35, 51);
empid = line.substring(22, 34);
department = line.substring (35, 46); 
  

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

Мой вопрос был бы в том, есть ли какой-либо простой способ сохранить координаты (индексы) подстроки и вызвать их позже проще? Пример

 name = (2,10);
surname = (11,21);
  


и т.д.

Или, возможно, какая-либо альтернатива использованию подстрок? Спасибо!

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

1. Я полагаю, вы могли бы поместить все координаты в массив и использовать карту для поиска в массиве на основе вашей входной строки.

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

3. @Loris Securo к сожалению, новые типы данных не совпадают

4. карта ключей «start» (строка), которая содержит значение пользовательского объекта (как предложено @AzizSonawalla ниже), который содержит начальный индекс, конечный индекс и пользовательскую функцию (или некоторое расширение функции), может подойти вам.

Ответ №1:

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

 public static void main( String[] args ) {

    Map<String, Map<String,IndexDesignation>> substringMapping = new HashMap<>();

    // Put all the designations of how to map here

    substringMapping.put( "03", new HashMap<>());
    substringMapping.get( "03" ).put( "name", new IndexDesignation(2,10));
    substringMapping.get( "03" ).put( "surname", new IndexDesignation(11,21));

    // This determines which mapping value to use
    Map<String,IndexDesignation> indexDesignationMap = substringMapping.get(args[0].substring(0,2));

    // This holds the results
    Map<String, String> resultsMap = new HashMap<>();

    // Make sure we actually have a map to use
    if ( indexDesignationMap != null ) {
        // Now take this particular map designation and turn it into the resulting map of name to values

        for ( Map.Entry<String,IndexDesignation> mapEntry : indexDesignationMap.entrySet() ) {
            resultsMap.put(mapEntry.getKey(), args[0].substring(mapEntry.getValue().startIndex,
                    mapEntry.getValue().endIndex));
        }
    }

    // Print out the results (and you can assign to another object here as needed)
    System.out.println( resultsMap );
}

// Could also just use a list of two elements instead of this
static class IndexDesignation {
    int startIndex;
    int endIndex;
    public IndexDesignation( int startIndex, int endIndex ) {
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }
}
  

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

1. Спасибо, вероятно, это то, что я искал. Я обязательно попробую.

Ответ №2:

Создайте класс с именем Line и сохраните эти объекты вместо строки:

 class Line {

  int[] name;
  int[] surname;
  int[] id;
  int[] address;

  String line;

  public Line(String line) {
    this.line = line;

    String startCode = line.substring(0, 3);
    switch(startCode) {
      case "03":
        this.name = new int[]{2, 10};
        this.surname = new int[]{11, 21};
        this.id = new int[]{22, 34};
        this.address = new int[]{35, 46};
        break;
      case "24":
        // same thing with different indices
        break;
      // add more cases
    }
  }

  public String getName() {
    return this.line.substring(this.name[0], this.name[1]);
  }

  public String getSurname() {
    return this.line.substring(this.surname[0], this.surname[1]);
  }

  public String getId() {
    return this.line.substring(this.id[0], this.id[1]);
  }

  public String getAddress() {
    return this.line.substring(this.address[0], this.address[1]);
  }
}
  

Тогда:

 String line = "03 ..."

Line parsed = new Line(line);
parsed.getName();
parsed.getSurname();
...
  

Если вы собираетесь извлекать name , surname и т.д. Из Line объекта несколько раз, вы даже можете кэшировать его в первый раз, чтобы не вызывать substring несколько раз

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

1. Дорогой Азис, спасибо вам за ответ. К сожалению, каждый начальный код содержит новые типы данных, не всегда имя, фамилию и т. Д

Ответ №3:

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

Скажем, у нас есть текстовый файл, подобный этому —

 03SomeNameSomeSurname
24SomeName10000
  

Шаблон регулярных выражений имеет имя группы для присвоения имени атрибута анализируемому тексту. Итак, шаблон для первой строки —

 ^03(?<name>.{8})(?<surname>.{11})
  

Код является —

 public static void main(String[] args) {

        // Fixed Width File Lines
        List<String> fileLines = List.of(
                "03SomeNameSomeSurname",
                "24SomeName10000"
        );
        // List all regex patterns for the specific file
        List<Pattern> patternList = List.of(
                Pattern.compile("^03(?<name>.{8})(?<surname>.{11})"), // Regex for String - 03SomeNameSomeSurname
                Pattern.compile("^24(?<name>.{8})(?<salary>.{5})")); // Regex For String - 24SomeName10000

        // Pattern for finding Group Names
        Pattern groupNamePattern = Pattern.compile("\?<([a-zA-Z0-9]*)>");

        List<List<String>> output  = fileLines.stream().map(
                line -> patternList.stream() // Stream over the pattern list
                        .map(pattern -> pattern.matcher(line)) // Create a matcher for the fixed width line and regex pattern
                        .filter(matcher -> matcher.find()) // Filter matcher which matches correctly
                        .map( // Transform matcher results into String (Group Name = Matched Value
                                matcher ->
                                        groupNamePattern.matcher(matcher.pattern().toString()).results() // Find Group Names for the regex pattern
                                                .map(groupNameMatchResult -> groupNameMatchResult.group(1)   "="   matcher.group(groupNameMatchResult.group(1))) // Transform into String (Group Name = Matched Value)
                                .collect(Collectors.joining(","))) // Join results delimited with ,
                        .collect(Collectors.toList())
        ).collect(Collectors.toList());

        System.out.println(output);
    }
  

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

 [[name=SomeName,surname=SomeSurname], [name=SomeName,salary=10000]]