Разбиение строки на части и сохранение в CSV с помощью JAVA - PullRequest
0 голосов
/ 02 февраля 2020

У меня есть данные в разных форматах. Я хочу, чтобы сначала из входной строки извлекалось Количество , а затем Единица , а оставшийся текст следует рассматривать как элемент .

Код. java

  public String itemsProcesing(List<String> items) throws IOException {
        List<String> list = items;
        List<String> unitList = Arrays.asList("g", "tbsp", "cm", "kg"");
        List<String> quantityList = Arrays.asList("Full", "Quarter", "Half", "3 Quarter", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0");

        for (String s : list) {
            String[] strArr = s.split(" ");
            if (strArr.length == 2) {
                String newStr = rewriteString(strArr, quantityList);
                strArr = newStr.split(" ");
            }
            String[] itemLine = new String[3];
            for (int i = 0; i < strArr.length; i++) {
                String str = strArr[i];
                int index = findValueLocation(str, unitList);
                itemLine[index] = str;
            }
            String line = createLineForCSV(itemLine);
            writeToFile(line);

        }


        return "done";
    }

    private static int findValueLocation(String str, List<String> unitList) {
         boolean b = Pattern.matches("\\d{1,3}|\\d/\\d|\\d/\\d[*]\\d|\\d{1,3}[*]\\d{1,3}|\\d{1,3}[*]\\d{1,3}|\\d{1,3}[-]\\d{1,3}|\\d{1,3} [-] \\d{1,3}|\\d.\\d|\\\\d{1,3} - \\\\d{1,3}| \\\\d{1,3} - \\\\d{1,3}| \\\\d{1,3}-\\\\d{1,3}", str);
        if (b) {
            return 0;
        }

        for (String unit : unitList) {
            if (unit.equals(str)) {
                return 1;
            }
        }
        return 2;
    }

    private static String createLineForCSV(String[] itemLine) {
        StringBuilder sb = new StringBuilder();
        sb.append(itemLine[0]).append(",");
        sb.append(itemLine[1]).append(",");
        sb.append(itemLine[2]);
        return sb.toString();
    }

    private static void writeToFile(String line) throws IOException {
        BufferedWriter writer = new BufferedWriter(new FileWriter("csv_file.csv", true));
        writer.write(line);
        writer.newLine();
        writer.close();
    }

    private static String rewriteString(String[] arr, List<String> quantityList) {
        String strOne = arr[0];
        String strTwo = arr[1];
        String newStr = "";
        for (String quantity : quantityList) {
            if (strOne.contains(quantity)) {
                // 8g carrots becomes "8 g carrots"
                newStr = quantity + " " + strOne.substring(quantity.length()) + " " + strTwo;
                break;
            } else if (strTwo.contains(quantity)) {
                newStr = quantity + " " + strTwo.substring(quantity.length()) + " " + strOne;
                break;
            }
        }
        return newStr;
    }

Исходные данные 1-2 столовые ложки соевого соуса

Ouptut : 1-2, столовые ложки, соус

Требуемый выход : 1-2, столовые ложки, соевый соус

Как я мог получить требуемые результаты.

Ответы [ 3 ]

2 голосов
/ 02 февраля 2020

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

Примерно так:

Pattern p=Pattern.compile("(.*?)\\s*(tbsp|k?g|cup|c?m)\\s*(.*)");
List<String> tests=Arrays.asList(
  "16g salt",
  "1 kg apple",
  "1 1/2 tbsp sugar");
for(String s:tests){
  Matcher m=p.matcher(s);
  if(m.matches())
    System.out.println(Arrays.asList(m.group(1),m.group(2),m.group(3)));
}

Вывод (из https://ideone.com/9kbozK):

[16, g, salt]
[1, kg, apple]
[1 1/2, tbsp, sugar]

В реальной жизни должна существовать ветвь else для определения возможных ошибок (или нераспознанных единиц) при вводе.

1 голос
/ 02 февраля 2020

Вы можете поместить все это в одно ужасное регулярное выражение (может потребоваться некоторая подстройка)

"((\\d+([/\\\\*]\\d+)?)\\s*(-\\s*\\d+([/\\\\*]\\d+)?)?\\s*(Full|Quarter|Half|3 Quarter)?)\\s*(g|tbsp|cm|kg)?\\s*(\\w*.*)"

и выбрать группу 1, группу 7 и группу 8.

Я не был ' Я не совсем уверен, куда поместить Quarter et c, количество, единицу или оба в вашем источнике, вы используете его для форматирования, как я вижу ...

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RecepieSplitter {

    private static final Pattern INGREDIENT_PATTERN = Pattern.compile(
            "((\\d+([/\\\\*]\\d+)?)\\s*(-\\s*\\d+([/\\\\*]\\d+)?)?\\s*(Full|Quarter|Half|3 Quarter)?)\\s*(g|tbsp|cm|kg)?\\s*(\\w*.*)");

    public static List<String> getParts(String ingredient) {
        Matcher matcher = INGREDIENT_PATTERN.matcher(ingredient);
        if (matcher.matches()) {
            return Arrays.asList(matcher.group(1), matcher.group(7), matcher.group(8));
        }
        return null;
    }

    public static void main(String[] args) {
        System.out.println(RecepieSplitter.getParts("1-2 tbsp soya sauce"));
        System.out.println(RecepieSplitter.getParts("8g carorts"));
        System.out.println(RecepieSplitter.getParts("1/4kg carorts"));
        System.out.println(RecepieSplitter.getParts("1/4 - 1/2g carorts"));
        System.out.println(RecepieSplitter.getParts("1 - 2Quarter carorts"));
    }
}

Вывод:

[1-2 ст. Ложки соевого соуса]

[8, г, кареты]

[1/4, кг, кареты]

[1 / 4 - 1/2, г, carorts]

[1 - 2 квартал, ноль, carorts]

1 голос
/ 02 февраля 2020

Проблема здесь в этой строке при обработке предметов: int index = findValueLocation(str, unitList); itemLine[index] = str;

Функция 'findValueLocation' вернет 2 для обеих строк 'соя' и 'соус'. Теперь он перезаписывает строку «соя» и записывает «соус» в индекс 2. Вы должны объединить строку, если возвращаемое значение равно 2.

`

int index = findValueLocation(str, unitList);
 if(index == 2){
     itemLine[index] += str;
 }else{
     itemLine[index] = str;
 }

`

...