【问题标题】:Partial String matching using Java8 Streams使用 Java8 Streams 进行部分字符串匹配
【发布时间】:2018-03-26 08:01:05
【问题描述】:

我检查了以下链接 - Link1 Link2 Link3 但无法解决并因此发布。

需要:

2 个字符串字段的字符串部分匹配(并非在所有情况下都可以完全匹配)并从匹配的行中获取信息。数据存储在 MySQL 数据库中。

事务数据表包含需要与 Scrip-Info 表中的公司名称进行比较的描述。我需要从 Scrip-Info Table 中获取公司代码信息,方法是将 Transaction Table 中的尽可能多的单词匹配到 Scrip Info Table

代码:

for (List<String> listData : transactionData) {
       List<List<String>> code = scripInfo.stream()
                .filter(p -> p.get(1).toUpperCase().contains(listData.get(1).toUpperCase()))
                .collect(Collectors.toList());
// Output to console to check if its working
code.forEach(p -> System.out.println(p.get(0)));
//Prepare Output List
List<Object> rowData = new ArrayList<>();
rowData.add(code.get(0));
rowData.add(listData.get(2));
rowData.add(listData.get(3));
.........

}

虽然我在上面的代码中使用了“包含”,但它只有在完全匹配时才会获取数据。所以从下面我提供的示例数据中,我只找到了 CANARA BANK,因为它在两个表中都是相同的

注意:数据存储在 MySQL db 中并提取。

脚本信息表

  • [BHARTIARTL, Bharti Airtel Limited]
  • [BHEL,巴拉特重型电气有限公司]
  • [CANBK, Canara 银行]
  • [HINDUNILVR,印度斯坦联合利华有限公司]
  • [MARUTI, Maruti Suzuki India Limited]
  • [TATAPOWER, 塔塔电力有限公司]
  • [TATASTEEL, 塔塔钢铁有限公司]
  • [TECHM, Tech Mahindra Limited]

交易数据表

  • [10144, CANARA 银行, B, 100]
  • [10278, BHARTI AIRTEL LTD, B, 50]
  • [10278, BHARTI AIRTEL LTD, B, 20]
  • [10278, HIND.UNILEVER LTD., B, 12]
  • [10278, HIND.UNILEVER LTD., B, 32]
  • [10278, MARUTI SUZUKI INDIA LTD., S, 26]
  • [10278, MARUTI SUZUKI INDIA LTD., S, 26]
  • [10278, TECHM FUT 28AUG 14, S, 125]
  • [10278, TECHM FUT 28AUG 14, B, 125]
  • [11585, TATA STEEL LTD., B, 50]
  • [11585, TATA POWER CO. LTD., B, 100]

所需输出:

  • [CANBK,B,100]
  • [BHARTIARTL,B,50]
  • [BHARTIARTL,B,20]
  • [BHARTIARTL,B,80]
  • [HINDUNILVR,B,12]
  • [HINDUNILVR,B,32]
  • [HINDUNILVR,B,52]
  • [马鲁蒂,S,26]
  • [马鲁蒂,B,26]
  • [TECHM, S, 125]
  • [TECHM, B, 125]
  • [TATASTEEL,B,50]
  • [TATAPOWER, B, 100]

当前代码的输出:

  • [CANBK,B,100]

【问题讨论】:

  • p.get(1) 在做什么?为什么你认为contains 应该做你想做的输出?
  • p.get(1) 从 Scrip-Info 表中获取公司名称信息,转换为大写并进行比较。我对 contains 的理解是,它会尝试匹配 LtoR 中的尽可能多的单词,我想我的理解可能偏离目标。
  • 请阅读 contains 的 java 文档。您可能希望为您的用例实现匹配算法,将简写名称绑定到全名中,或者将此类名称的映射保留在另一个数据结构中,可以在当前循环中查找。

标签: java java-8 java-stream string-matching


【解决方案1】:

您可以使用过滤部分。这是一个例子,

    List<TransactionData> filteredData =
            transactionData.stream().filter(t ->
            {
                List<ScripInfo> filteredScrip =
                        scripInfo.stream().filter(s -> {
                            String[] tranTokens =
                                    t.getName().toUpperCase().split(
                                            " |\\.");
                            String[] scripTokens =
                                    s.getName().toUpperCase().split(" ");
                            String scripSysmbol =
                                    s.getSymbol().toUpperCase();
                            if (tranTokens[0].contains(scripTokens[0])) {
                                return true;
                            } else if (scripSysmbol.contains(
                                    tranTokens[0])) {
                                return true;
                            }
                            return false;
                        }).collect(Collectors.toList());

                return filteredScrip.size() > 0 ? true : false;

            }).collect(Collectors.toList());

在我的示例中,ScripInfoTransactionData 类是简单的 POJO,

@Data
@AllArgsConstructor
public class ScripInfo {
    private String symbol;

    private String name;
}

@Data
@AllArgsConstructor
public class TransactionData {
    private String name;

    private String letter;

    private int number;
}

【讨论】:

    猜你喜欢
    • 2020-10-16
    • 2018-10-13
    • 1970-01-01
    • 1970-01-01
    • 2017-04-02
    • 1970-01-01
    • 2019-11-01
    • 2012-06-15
    • 1970-01-01
    相关资源
    最近更新 更多