C ++删除Dupes

时间:2015-10-13 09:01:32

标签: c++

我有一些代码: 我需要删除重复项,我真的不知道哪个步骤出错了。 有点失去了睡眠。 我觉得我已经不必要地过度复杂了,但是脑子里已经死了,看看我哪里出错了。

仍有问题=(

我正在根据建议进行改变...即使我的arr大小为8,仍然会跑出界限... 我已经尝试过打印值,它似乎在第3个元素上出乎意料地突破但我不知道该怎么做。任何其他帮助将不胜感激...

template <typename T>
void removeDup(std::vector<T> & v)
{
int last = v.size()-1;
for(int i = 0; i <= v.size(); i++)
    {
            if (count(v, i, last, v[i]) > 1){ // if there is more than 1
            v.erase(v.begin()+(i)); // erase it
            }
        }
}


template <typename T>
int count(const std::vector<T> & v, int first, int last, const T& target){

    int index = first;
    int count = 0;

for (index; index < last; index++){
if (v[index] == target){
    count++;
    }
}

return count;
}

template <typename T>
int seqVectSearch(const std::vector<T> & v, int first, int last, const T& target){

    int index = first;
    int returnVal = -1;

for (index; index < last; index++){
if (v[index] == target){
    returnVal = index;
    }
}

return returnVal;
}

template <typename T>
void writeVector(const std::vector<T> & v){
    int i;
    int n = v.size();

    for (i = 0; i < n; i++)
        std::cout << v[i] << ' ';
        std::cout << std::endl;
}

template void removeDup(std::vector<int> & v);
template int seqVectSearch(const std::vector<int> & v, int first, int last, const int& target);
template void writeVector(const std::vector<int> & v);
template int count(const std::vector<int> & v, int first, int last, const int& target);

输出:

Testing removeDup
Original vector is  1 7 2 7 9 1 2 8 9
Vector with duplicates removed is  1 2 7 9 1 2 8 9

1 2 7 9 1 2 8 9
Press any key to continue . . .

3 个答案:

答案 0 :(得分:1)

如果您删除某个项目,则需要测试下一个项目 保持你刚刚测试的位置,所以更新 在这种情况下索引是不对的。 erase返回一个迭代器,如果你愿意,它可以很方便 迭代并有条件地删除一些项目 另请注意count中已定义<algorithm>, 你不需要定义自己的。

template <typename T>
void removeDup(std::vector<T>& v)
{
    auto iter = v.begin()
    while( iter != v.end() )
    {
        if( std::count(iter, v.end(), *iter) > 1)
            iter = v.erase(iter);
        else
            ++iter;
    }
}
然而,请注意,这会改变很多物品, 并且erase-remove idiom可能更适合。

答案 1 :(得分:1)

这是一个稳定的解决方案(保留元素的相对顺序),使用C ++标准模板库中的std::remove_if()。正如您所看到的,实际删除重复项只需要大约10行实际代码;其余的(遗憾的是)C ++噪音包含文件和“漂亮”打印容器到stdout。

核心思想是保留一组已经在谓词中看到的元素;如果元素是重复的(即可以删除),则谓词是返回true的仿函数,否则返回false

复杂性应该是O(n)+ O(n log n) - 每个元素需要检查一次,set中的查找是O(n log n)。

#include <set>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

template <typename T>
struct remove_dups_predicate {
    typedef std::set<T> unique_values_t;


    // Return true if we've seen this element before
    // note that set.insert(...) returns pair<iterator,bool>
    // with the bool telling wether or not the element was 
    // succesfully inserted, i.e. it should *not* be removed
    bool operator()(const T& element) {
        return !unique_values_seen.insert(element).second;
    }
    unique_values_t  unique_values_seen;
};

int main( void ) {
    std::vector<int>           vi{ 1, 7, 2, 7, 9, 1, 2, 8, 9};

    std::cout << "Before: ";
    std::copy(vi.begin(), vi.end(), std::ostream_iterator<int>(std::cout, ", "));
    std::cout << std::endl;

    // Remove the duplicates
    std::vector<int>::iterator it = std::remove_if(vi.begin(), vi.end(),
                                                   remove_dups_predicate<int>());

    // print to stdout
    std::cout << "After: ";
    std::copy(vi.begin(), it, std::ostream_iterator<int>(std::cout, ", "));
    std::cout << std::endl;

    return 0;
}

运行此项作为输出:

Before: 1, 7, 2, 7, 9, 1, 2, 8, 9,
After: 1, 7, 2, 9, 8,

答案 2 :(得分:-1)

关于算法存在一些错误。主要是范围问题。

v.erase(v.begin()+(i-1));

您的i变量从0开始,因此您不需要删除之前的元素。只需删除begin()+i

count(v, i, last, i)

您已通过last count(...) size()-1 index <= last的价值。因此,您的迭代必须等到index < last,而不仅仅是i

另一个问题,第四个参数不是v[i],是template <typename T> void removeDup(std::vector<T> & v) { for(int i = 0; i <= v.size(); i++) { if (count(v, i, v[i]) > 1){ // if there is more than 1 v.erase(v.begin()+i); // erase it i--; // Decrement to stay at the same index. } } } template <typename T> int count(const std::vector<T> & v, int first, const T& target){ int count = 0; for (int index = first; index < v.size(); index++){ if (v[index] == target){ count++; } } return count; } 。您的代码只能编译,因为您正在使用整数向量进行测试,这是一种相同类型的索引。

它可能有其他错误,请仔细查看算法和索引范围。一个好的选择是打印功能的每一步。

编辑:添加我建议的算法

这是两个核心方法的代码。如果您想在其他任务中使用类似的东西,请复制逻辑。

extension WKWebView {
    private struct key {
        static let scale = unsafeBitCast(Selector("scalesPageToFit"), UnsafePointer<Void>.self)
    }
    private var sourceOfUserScript: String {
        return "(function(){\n" +
            "    var head = document.getElementsByTagName('head')[0];\n" +
            "    var nodes = head.getElementsByTagName('meta');\n" +
            "    var i, meta;\n" +
            "    for (i = 0; i < nodes.length; ++i) {\n" +
            "        meta = nodes.item(i);\n" +
            "        if (meta.getAttribute('name') == 'viewport')  break;\n" +
            "    }\n" +
            "    if (i == nodes.length) {\n" +
            "        meta = document.createElement('meta');\n" +
            "        meta.setAttribute('name', 'viewport');\n" +
            "        head.appendChild(meta);\n" +
            "    } else {\n" +
            "        meta.setAttribute('backup', meta.getAttribute('content'));\n" +
            "    }\n" +
            "    meta.setAttribute('content', 'width=device-width, user-scalable=no');\n" +
        "})();\n"
    }
    var scalesPageToFit: Bool {
        get {
            return objc_getAssociatedObject(self, key.scale) != nil
        }
        set {
            if newValue {
                if objc_getAssociatedObject(self, key.scale) != nil {
                    return
                }
                let time = WKUserScriptInjectionTime.AtDocumentEnd
                let script = WKUserScript(source: sourceOfUserScript, injectionTime: time, forMainFrameOnly: true)
                configuration.userContentController.addUserScript(script)
                objc_setAssociatedObject(self, key.scale, script, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                if URL != nil {
                    evaluateJavaScript(sourceOfUserScript, completionHandler: nil)
                }
            } else if let script = objc_getAssociatedObject(self, key.scale) as? WKUserScript {
                objc_setAssociatedObject(self, key.scale, nil, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                configuration.userContentController.removeUserScript(script)
                if URL != nil {
                    let source = "(function(){\n" +
                        "    var head = document.getElementsByTagName('head')[0];\n" +
                        "    var nodes = head.getElementsByTagName('meta');\n" +
                        "    for (var i = 0; i < nodes.length; ++i) {\n" +
                        "        var meta = nodes.item(i);\n" +
                        "        if (meta.getAttribute('name') == 'viewport' && meta.hasAttribute('backup')) {\n" +
                        "            meta.setAttribute('content', meta.getAttribute('backup'));\n" +
                        "            meta.removeAttribute('backup');\n" +
                        "        }\n" +
                        "    }\n" +
                    "})();"
                    evaluateJavaScript(source, completionHandler: nil)
                }
            }
        }
    }
}
extension WKUserContentController {
    public func removeUserScript(script: WKUserScript) {
        let scripts = userScripts
        removeAllUserScripts()
        scripts.forEach {
            if $0 != script { self.addUserScript($0) }
        }
    }
}