Сравнение данных в двух файлах Excel и запись соответствующих отображений в третий файл - PullRequest
0 голосов
/ 24 января 2019

У меня есть список лекарственных веществ с соответствующими идентификаторами в двух листах Excel, взятых из двух разных источников данных, например

Данные Всемирной организации здравоохранения: enter image description here

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

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

Идентификатор продукта1 Идентификатор продукта2 Вещество1 Вещество2 Вещество3 Вещество4 .....

Примечание - продукт может содержать более 100 веществ.

Вот способ, которым я пытаюсь решить эту проблему, но мне нужна помощь:

  1. Считать данные с обоих листов и поместить в Карты

  2. Сравните две карты (вот где у меня возникли проблемы)

  3. Запись данных, сопоставленных с файлом Excel.

public static void main(String[] args) {

    String readFile = "C:\\Users\\admin\\Desktop\\SampleData";
    HashMap<Double, Set<Object>> productMapWHO = new HashMap<Double, Set<Object>>();
    HashMap<Double, Set<Object>> productMapNDC = new HashMap<Double, Set<Object>>();
    productMapWHO = readExcel(0, readFile);
    productMapNDC = readExcel(1, readFile);

    Map<Double,Map<Double,Set<Object>>> WHOtoNDCMapping = new HashMap<Double,Map<Double,Set<Object>>>();

    WHOtoNDCMapping = compareProductMaps(productMapWHO,productMapNDC);

    String writeFile = "C:\\Users\\admin\\Desktop\\WHO_NDC_Mapping.xls";

    try {
        writeToExcel(WHOtoNDCMapping,writeFile);
    } catch (InvalidFormatException e) {
        e.printStackTrace();
    } catch (HPSFException e) {
        e.printStackTrace();
    }

}


private static HashMap<Double, Set<Object>> readExcel(int sheetNumber, String fileName) {


    HashMap<Double, Set<Object>> productMap = new HashMap<Double, Set<Object>>();

    try {
        FileInputStream file = new FileInputStream(new File(fileName));

        //Create Workbook instance holding reference to .xlsx file
        XSSFWorkbook workbook = new XSSFWorkbook(file);
        //Get first/desired sheet from the workbook
        XSSFSheet sheet = workbook.getSheetAt(sheetNumber);
        //Iterate through each rows one by one
        Iterator<Row> rowIterator = sheet.iterator();

        while (rowIterator.hasNext()) {

            List<String> substancelist = new ArrayList<String>();

            Row row = rowIterator.next();

            double key;
            Object value="";
            //substancelist.clear();
            Iterator<Cell> cellIterator = row.cellIterator();
            Cell cell =null;
            while (cellIterator.hasNext()) {

                if(cell.getColumnIndex() == 1)
                    key = cell.getNumericCellValue();

                switch (cell.getCellType())
                {
                case Cell.CELL_TYPE_NUMERIC:
                    value = cell.getNumericCellValue();
                    break;

                case Cell.CELL_TYPE_STRING:
                    value = cell.getStringCellValue().trim();
                    break;

                }

                Set<Object> list = productMap.get(key);
                if (list == null) productMap.put(key, list = new HashSet<Object>());
                list.add(value);
            }
        }
    }

    catch (Exception e) {
        e.printStackTrace();
    }
    return productMap;
}


private static Map<Double,Map<Double,Set<Object>>> compareProductMaps (HashMap<Double, Set<Object>>productMap1, HashMap<Double, Set<Object>>productMap2) {

    Map<Double,Map<Double,Set<Object>>> finalMapping = new HashMap<Double,Map<Double,Set<Object>>>();


    for(Map.Entry<Double, Set<Object>> entry : productMap1.entrySet()) {
        Double key = entry.getKey();
        Map<Double,Set<Object>> mappedIds = new HashMap<Double, Set<Object>>();
        for(Set<Object> valueList : productMap1.values()) {
            if (valueList.size() == productMap2.values().size() && productMap2.values().containsAll(valueList))
            {
                Double productId2 = productMap2.get(valueList); //throws error here. I want to get the key for the corresponding valuelist that matched.
                mappedIds.put(productId2,valueList);
                finalMapping.put(key,mappedIds);
            }
        }
    }


    return finalMapping;

}

private static void writeToExcel(Map<Double,Map<Double,Set<Object>>> finalMapping, String xlsFilename) throws HPSFException, InvalidFormatException {


    Workbook wb = null;

    try {
        wb = WorkbookFactory.create(new FileInputStream(xlsFilename));
    } catch (EncryptedDocumentException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    Sheet sheet = wb.createSheet("WHOtoNDCMapping");

    int rowIdx = 0;
    int cellIdx = 0;

    // Header
    Row hssfHeader = sheet.createRow(rowIdx);


    rowIdx = 1;
    Row row = sheet.createRow(rowIdx++);
    cellIdx = 0;

    for(Double productId1 : finalMapping.keySet()) {
        Map<Double,Set<Object>> m1 = finalMapping.get(productId1);
        Cell cell = row.createCell(cellIdx++);
        cell.setCellValue(productId1);

        for(Double productId2 : m1.keySet()) {
            Set<Object> substanceList = m1.get(productId2);
            cell = row.createCell(cellIdx++);
            cell.setCellValue(productId2);

            for (Object substance : substanceList){
                if (substance instanceof String) {
                    cell.setCellValue((String) substance);
                } else if (substance instanceof Number) {
                    cell.setCellValue(((Number) substance).doubleValue());
                } else {
                    throw new RuntimeException("Cell value of invalid type " + substance);
                }
            }
        }
    }
    try {
        FileOutputStream out = new FileOutputStream(xlsFilename);
        wb.write(out);
        out.close();
    } catch (IOException e) {
        throw new HPSFException(e.getMessage());
    }
}

1 Ответ

0 голосов
/ 24 января 2019

Я бы не использовал карты карт и т. Д., Но создал бы класс, который правильно представляет продукт.Если структура обоих файлов одинакова, вы можете использовать что-то вроде этого (упрощенно, я оставлю некоторую работу для вас;)):

class ExcelProduct {
  String productId;
  String productName;
  Set<String> substanceIds; //assuming order is not relevant, otherwise use a list
}

Тогда вы можете прочитать это в Map<String, ExcelProduct> гдеключ - идентификатор продукта и, наконец, работа с этими картами, например, путем перебора одной из карт и получения соответствующего продукта со второй карты:

for( ExcelProduct leftProduct : leftMap.values() ) {
  ExcelProduct rightProduct = rightMap.get(leftProduct.productId);

  //product not present in right map so skip
  if( rightProduct == null ) {
    continue;
  }

  //compare products here, e.g. comparing the substance ids
  if( leftProduct.substanceIds.equals( rightProduct.substanceIds) ) {
    //do whatever is needed, e.g. add the product to the result list which will be written to the result excel file
    //you probably don't need a result map here
  }
}

Обратите внимание, что правильность работы leftProduct.substanceIds.equals( rightProduct.substanceIds) зависит откакую реализацию набора вы используете, но встроенные реализации должны использовать AbstractSet.equals(), который, если переданный объект также является набором, будет сравнивать размеры и будет ли один из наборов содержать все элементы другого (что означает, что есливсе элементы присутствуют, и их размер одинаков, отсутствующие / дополнительные элементы не могут быть, потому что наборы не могут содержать дубликаты).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...