【问题标题】:C++ Remove string as duplicate in vector based on partial match of substringC ++根据子字符串的部分匹配将字符串删除为向量中的重复项
【发布时间】:2020-08-09 23:54:46
【问题描述】:

有没有一种有效的方法可以根据子字符串的匹配将字符串作为重复项删除?

考虑一个包含多个相同格式的 CSV 字符串的向量(combinedvect):

'QWERTY, PROTMD, PEDKF, 12345.15454'
'ASDFGH, LDMEMA, PWEMDE, 23456.938984'
'ZXCVBN, NMDFN, MNMWNS, 34567.903'
'ASDFGH, LDMEMA, PWEMDE, 23444.624'
'QWERTY, PROTMD, PEDKF, 15654.15454'

反向排序使用:

std::sort (combinedvect.begin(), combinedvect.end(), std::greater<>());

结果:

 'ZXCVBN, NMDFN, MNMWNS, 34567.903'
 'QWERTY, PROTMD, PEDKF, 15654.15454'
 'QWERTY, PROTMD, PEDKF, 12345.15454'
 'ASDFGH, LDMEMA, PWEMDE, 23456.938984'
 'ASDFGH, LDMEMA, PWEMDE, 23444.624'

反向排序用于按数字子串从高到低的顺序列出重复项,如:

 'QWERTY, PROTMD, PEDKF, 15654.15454'
 'QWERTY, PROTMD, PEDKF, 12345.15454'

目标是删除前 3 个子字符串与前 3 个子字符串匹配的任何整个字符串,然后按数字子字符串的升序对结果输出进行排序。

输出应如下所示:

 'QWERTY, PROTMD, PEDKF, 15654.15454'
 'ASDFGH, LDMEMA, PWEMDE, 23456.938984'
 'ZXCVBN, NMDFN, MNMWNS, 34567.903'

拆分和映射函数,例如:

  void splitsort(const std::string &s, double &selectedLPLSQLDate, std::string &mycombinedtext) {
    size_t idx = s.find(',');
    mycombinedtext= s.substr(0, idx+2);
    selectedLPLSQLDate = std::stod(s.substr(idx+3));
}

bool mapFunc(const std::string &a, const std::string &b) {
    double selectedLPLSQLDate1, selectedLPLSQLDate2;
    std::string mycombinedtext1, mycombinedtext2;
    splitsort(a, selectedLPLSQLDate1, mycombinedtext1);
    splitsort(b, selectedLPLSQLDate2, mycombinedtext2);
    return selectedLPLSQLDate1 < selectedLPLSQLDate2;
}

不适合

std::sort (combinedvect.begin(), combinedvect.end(), mapFunc);

【问题讨论】:

    标签: c++ sorting vector


    【解决方案1】:

    这是你想要的工作:

    #include <vector>
    #include<string>
    #include<algorithm>
    #include<map>
    #include <iostream>
    
    int main()
    {
        std::vector<std::string> v{
                "QWERTY, PROTMD, PEDKF, 12345.15454",
                "ASDFGH, LDMEMA, PWEMDE, 23456.938984",
                "ZXCVBN, NMDFN, MNMWNS, 34567.903",
                "ASDFGH, LDMEMA, PWEMDE, 23444.624",
                "QWERTY, PROTMD, PEDKF, 15654.15454"
        };
        std::map<std::string, double> map;
        for(auto& el: v){
            auto it = el.find_last_of(',');           // find last ","
            auto key = el.substr(0, it);              // extract the key
            auto value = std::stod(el.substr(it+1));  // extract the last value
            if(map.find(key) == map.end() || (map.find(key) != map.end() && map[key] < value)) // if it does not exist already, or if it exists and has a value greater thatn the one inserted
                map[key] = value; // change the value
        }
        for(auto& [k, v]: map)
            std::cout << k << " : " << v << "\n";
    }
    

    然后您可以使用std::transform 构建一个std::string 加入映射键和值的数组,这应该是nlogn 复杂度,因为映射中的插入是logn,您最多会这样做n

    【讨论】:

    • 这会正确删除重复项。如果您需要保留所有十进制值,则必须将双精度更改为 std::string。此操作不会按数字子字符串的升序对结果输出进行排序。
    【解决方案2】:

    为了获得更实用的方法和更好的可读性,您应该将字符串转换为更合适的数据结构。两个字符串的简单对/元组就足够了(第一个表示三个子字符串,第二个表示数字子字符串)。结果看起来像这样(我把这个任务留给你):

    using namespace std::literals;
    auto csv = std::vector{std::pair{"QWERTY, PROTMD, PEDKF"s, "12345.15454"s},
                           std::pair{"ASDFGH, LDMEMA, PWEMDE"s, "23456.938984"s},
                           std::pair{"ZXCVBN, NMDFN, MNMWNS"s, "34567.903"s},
                           std::pair{"ASDFGH, LDMEMA, PWEMDE"s, "23444.624"s},
                           std::pair{"QWERTY, PROTMD, PEDKF"s, "15654.15454"s}};
    

    然后按照您的方式对列表进行排序(std::pair 将比较第一部分,只有相等时才考虑第二部分)。

    std::sort(csv.begin(), csv.end(), std::greater<>());
    

    然后您可以使用std::unique 删除所有重复项。您需要一个自定义谓词来仅比较第一个子字符串。

    const auto p = [](const auto& a, const auto& b) {
      return a.first == b.first;
    };
    csv.erase(std::unique(csv.begin(), csv.end(), p), csv.end());
    

    最后再排序,这次只比较第二部分(数字子串)。

    std::sort(csv.begin(), csv.end(),
              [](const auto& a, const auto& b) { return a.second < b.second; });
    

    由于std::sort,时间复杂度为O(n*log n)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-03
      • 1970-01-01
      • 2012-03-12
      • 1970-01-01
      • 2019-08-04
      相关资源
      最近更新 更多