场景
比如编辑联系人, 联系人需要加入某个分组, 这时候界面操作就需要复选框来选择加入某个分组, 但是有可能这个联系人之前已经加入了某个分组, 现在只是需要加入新的分组即可, 但是界面操作往往用户可能并不知道这个联系人已经加入过哪些分组, 所以他会把想加入的分组都勾选一边, 这样我们程序在提交时就需要过滤出未加入过的分组,也就是”相对补集”;
再比如, 修改用户资料时, 我们需要勾选多个爱好兴趣, 也会发生用户重复勾选已经选择过的爱好兴趣的情况.
再比如,用户也有可能取消勾选, 这样还是得计算”相对补集”作为需要删除得集合, 所以相对补集是比较常见的.
说明
C++ 的 stl algorithm 里提供了这类操作的模板函数, 而 Object-C就少写, 它作为 NSMutableSet的方法出现.
C++ 的 集合模板函数在使用前需要排序, 而 NSMutableSet 的方法却不用, 执行效率还是CPP更快, 当然 NSLog删除后性能有所提升, 但是还是不如删除 std::cout的 CPP实现.10倍左右.
例子
//
// TestSet.h
// TestObject-C
//
// Created by sai on 10/26/17.
// Copyright (c) 2017 sai. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface TestSet : NSObject
+(void)testSet;
@end
//
// TestSet.mm
// TestObject-C
//
// Created by sai on 10/26/17.
// Copyright (c) 2017 sai. All rights reserved.
//
#import "TestSet.h"
#include <vector>
#include <chrono>
#include <iostream>
#include <sstream>
#include <algorithm>
@implementation TestSet
+(void)testCppSet
{
std::cout << "======== testCppSet ========" << std::endl;
auto beg = std::chrono::system_clock::now();
std::vector<int> v1 = {1,3,4,5,7,9,2};
std::vector<int> v2 = {2,3,6,7,7,10};
std::stringstream ss;
for (int one : v1) {
ss << one << ",";
}
std::string str = ss.str();
std::cout << "v1: " << str << std::endl;
ss.clear();
ss.str("");
for (int one : v2)
ss << one << ",";
str = ss.str();
std::cout << "v2: " << str << std::endl;
std::vector<int> d1;
auto last = std::unique(v1.begin(),v1.end());
v1.erase(last, v1.end());
d1.clear();
last = std::unique(v2.begin(),v2.end());
v2.erase(last, v2.end());
std::cout << "=== v1和v2的交集 ===" << std::endl;
ss.clear();
ss.str("");
std::sort(v1.begin(),v1.end());
std::sort(v2.begin(),v2.end());
std::vector<int> result;
std::set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),std::back_inserter(result));
for (int one : result)
ss << one << ",";
str = ss.str();
std::cout << str << std::endl;
std::cout << "=== v1在v2中的相对补集 ===" << std::endl;
ss.clear();
ss.str("");
std::set_difference(v2.begin(),v2.end(),result.begin(),result.end(),std::back_inserter(d1),
[](const int first,const int second)->bool{
return first < second;
});
for (int one : d1)
ss << one << ",";
str = ss.str();
std::cout << str << std::endl;
std::cout << "=== v1和v2的合集 ===" << std::endl;
ss.clear();
ss.str("");
d1.clear();
std::set_union(v1.begin(),v1.end(),v2.begin(),v2.end(),std::back_inserter(d1));
for (int one : d1)
ss << one << ",";
str = ss.str();
std::cout << str << std::endl;
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-beg;
std::cout << "elapsed_seconds: "<< elapsed_seconds.count() << "s" << std::endl;
}
+(void)testObjectCSet
{
std::cout << "testObjectCSet" << std::endl;
auto beg = std::chrono::system_clock::now();
NSMutableString* str = [NSMutableString new];
[str autorelease];
NSArray* a = [NSArray arrayWithObjects:@(1),@(3),@(4),@(5),@(7),@(9),@(2), nil];
for (NSNumber* one in a) {
[str appendFormat:@"%lld,",[one longLongValue]];
}
NSLog(@"v1: %@,",str);
[str setString:@""];
NSArray* b = [NSArray arrayWithObjects:@(2),@(3),@(6),@(7),@(7),@(10), nil];
for (NSNumber* one in b) {
[str appendFormat:@"%lld,",[one longLongValue]];
}
NSLog(@"v2: %@,",str);
NSMutableSet* v1 = [NSMutableSet setWithArray:a];
NSMutableSet* v1_copy = [NSMutableSet setWithSet:v1];
NSMutableSet* v2 = [NSMutableSet setWithArray:b];
NSMutableSet* v2_copy = [NSMutableSet setWithSet:v2];
NSLog(@"=== v1和v2的交集 ===");
[str setString:@""];
[v1_copy intersectSet:v2];
for (NSNumber* one in v1_copy) {
[str appendFormat:@"%lld,",[one longLongValue]];
}
NSLog(@"%@,",str);
[str setString:@""];
NSLog(@"=== v1在v2中的相对补集 ===");
[v2_copy minusSet:v1_copy];
for (NSNumber* one in v2_copy) {
[str appendFormat:@"%lld,",[one longLongValue]];
}
NSLog(@"%@,",str);
[str setString:@""];
NSLog(@"=== v1和v2的合集 ===");
[v1 unionSet:v2];
for (NSNumber* one in v1) {
[str appendFormat:@"%lld,",[one longLongValue]];
}
NSLog(@"%@,",str);
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-beg;
std::cout << "elapsed_seconds: "<< elapsed_seconds.count() << "s" << std::endl;
}
+(void)testSet
{
@autoreleasepool {
[self testObjectCSet];
[self testCppSet];
}
}
@end
输出
testObjectCSet
2017-10-26 17:00:56.129 TestObject-C[5957:303] v1: 1,3,4,5,7,9,2,,
2017-10-26 17:00:56.129 TestObject-C[5957:303] v2: 2,3,6,7,7,10,,
2017-10-26 17:00:56.130 TestObject-C[5957:303] === v1和v2的交集 ===
2017-10-26 17:00:56.131 TestObject-C[5957:303] 2,7,3,,
2017-10-26 17:00:56.131 TestObject-C[5957:303] === v1在v2中的相对补集 ===
2017-10-26 17:00:56.132 TestObject-C[5957:303] 6,10,,
2017-10-26 17:00:56.133 TestObject-C[5957:303] === v1和v2的合集 ===
2017-10-26 17:00:56.133 TestObject-C[5957:303] 9,5,1,10,6,2,7,3,4,,
elapsed_seconds: 0.004996s
======== testCppSet ========
v1: 1,3,4,5,7,9,2,
v2: 2,3,6,7,7,10,
=== v1和v2的交集 ===
2,3,7,
=== v1在v2中的相对补集 ===
6,10,
=== v1和v2的合集 ===
1,2,3,4,5,6,7,9,10,
elapsed_seconds: 0.000345s