提取两个数组的共同键名再此排序

本文介绍了一种处理联表查询返回的两个键名相同但字段不同的二维数组的方法。通过合并数组并处理重复键名,确保了数据完整性和一致性。此外,文章还展示了如何遍历这些数据并进行累加计算。

联表查询
两个返回值的处理方法:
public static function getUserConsume($period,$character){
$uid=self::getByCharacter($character);
if($uid&&$period){

$userconsumescore = self :: getuserconsumescore($period, $uid);
$userscore = self :: getuserscore($period, $uid);

---------上面返回两个键名相同的二维数组,但是返回字段不同
$keys = array_unique (array_merge(array_keys($userconsumescore), array_keys($userscore)));
//array_keys()获得数组的键名,array_merge()合并数组;如果键名有重复,该键的键值为最后一个键名对应的值(后面的覆盖前面的)。如果数组是数字索引的,则键名会以连续方式重新索引。
array_unique() 函数移除数组中的重复的值,并返回结果数组。当几个数组元素的值相等时,只保留第一个元素,其他的元素被删除。返回的数组中键名不变
sort($keys);//获得键名的数组
$outdates = array();
$showtotalconsumeaddgx = $showtotalconsumeaddhonor = $showtotaladdhonor = $showtotaladdgx = 0;
//print_r($userconsumescore);
//print_r($keys);

//foreach 循环日期
foreach($keys as $date){
//echo $date . "/n<br />";
$totaladdhonor = isset($userscore[$date]['totaladdhonor']) ? $userscore[$date]['totaladdhonor'] : 0;
$showtotaladdhonor += $totaladdhonor;

$totaladdgx = isset($userscore[$date]['totaladdgx']) ? $userscore[$date]['totaladdgx'] : 0;
$showtotaladdgx += $totaladdgx;

$totalconsumeaddgx = isset($userconsumescore[$date]['addgx']) ? $userconsumescore[$date]['addgx'] : 0;
$showtotalconsumeaddgx += $totalconsumeaddgx;

$totalconsumeaddhonor = isset($userconsumescore[$date]['addhonor']) ? $userconsumescore[$date]['addhonor'] : 0;
$showtotalconsumeaddhonor += $totalconsumeaddhonor;
//方便添加字段,和查阅
$outdates[$date] = array(
'time'=>$date,
'totaladdhonor' => $totaladdhonor,
'showtotaladdhonor' => $showtotaladdhonor,
'totaladdgx' => $totaladdgx,
'showtotaladdgx' => $showtotaladdgx,
'totalconsumeaddgx' => $totalconsumeaddgx,
'showtotalconsumeaddgx' => $showtotalconsumeaddgx,
'totalconsumeaddhonor' => $totalconsumeaddhonor,
'showtotalconsumeaddhonor' => $showtotalconsumeaddhonor );
}
}

return $outdates;
}

常规的方法:

public static function getUserConsume($period,$character){
$uid=self::getByCharacter($character);
if($uid&&$period){

$userconsumescore = self :: getuserconsumescore($period, $uid);
$userscore = self :: getuserscore($period, $uid);

$keys = array_unique (array_merge(array_keys($userconsumescore), array_keys($userscore)));
sort($keys);
foreach($keys as $date){

$return[$date]['time']=$userconsumescore[$date]['time'];
$return[$date]['totaladdhonor']=$userscore[$date]['totaladdhonor'];
$return[$date]['showtotaladdhonor'] +=$userscore[$date]['totaladdhonor'];

$return[$date]['totaladdgx']=$userscore[$date]['totaladdgx'];
$return[$date]['showtotaladdgx'] +=$userscore[$date]['totaladdgx'];

$return[$date]['totalconsumeaddgx'] =$userconsumescore[$date]['addgx'];
$return[$date]['showtotalconsumeaddgx'] +=$userconsumescore[$date]['addgx'];
$return[$date]['totalconsumeaddhonor'] =$userconsumescore[$date]['addhonor'];
$return[$date]['showtotalconsumeaddhonor'] +=$userconsumescore[$date]['addhonor'];
}

return $return;
}
}

<think>我们正在讨论如何在C++中提取两个数组相同元素。根据用户提供的引用,有两种主要方法:使用List或Set(特别是基于红黑树的set或基于哈希的unordered_set)。在引用[2]中提到了set和hash_set(即unordered_set)的使用,以及它们底层的数据结构(红黑树和哈希表)。 在C++中,我们可以使用标准库提供的set或unordered_set来提高查找效率。具体步骤如下: 1. 将其中一个数组的元素存入一个集合(set或unordered_set)中,这样可以利用集合的快速查找特性(set的查找复杂度为O(log n),unordered_set的平均查找复杂度为O(1))。 2. 遍历另一个数组,检查每个元素是否存在于集合中,如果存在,则将其添加到结果容器中。 另外,也可以先对两个数组进行排序,然后使用双指针法来找出相同的元素。但是,根据引用[2]中提到的leetcode题目(349题)的解法,使用集合是更常见的方法。 下面我将展示两种方法: 方法一:使用unordered_set(哈希集合) 步骤: a) 创建一个unordered_set,用于存储第一个数组的元素。 b) 创建一个结果容器(如vector),用于存储相同的元素。 c) 遍历第二个数组,对于每个元素,检查它是否在unordered_set中,如果在则加入到结果容器中,同时为了避免重复添加相同的元素,可以在加入后从集合中移除该元素(如果两个数组中可能有重复元素,且我们要求结果中每个相同元素只出现一次,则这样做;如果要求保留重复次数,则不能移除,但需要处理重复情况,通常题目要求唯一)。 注意:如果两个数组中元素可能重复,且我们希望结果中相同元素出现的次数为两个数组中出现次数的最小,那么这种方法需要额外的计数。但题目中通常要求结果中的元素唯一(如349题),所以我们可以先对第一个数组去重。 方法二:使用set(红黑树实现的集合) 步骤类似,但set会自动去重并排序。 此外,还有一种排序加双指针的方法: 步骤: a) 对两个数组进行排序。 b) 使用两个指针分别指向两个数组的起始位置。 c) 比较两个指针指向的元素,如果相等,则加入结果(注意去重),然后两个指针同时后移;如果不相等,则较小元素的指针后移。 下面我们分别给出示例代码: 方法一:使用unordered_set(推荐,平均O(n)) ```cpp #include <iostream> #include <vector> #include <unordered_set> using namespace std; vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { unordered_set<int> set(nums1.begin(), nums1.end()); vector<int> res; for (int num : nums2) { if (set.erase(num)) { // 这里erase会删除元素并返回删除个数,如果存在则删除并返回1(即true),这样可以避免重复添加 res.push_back(num); } } return res; } ``` 方法二:使用sort+双指针(如果要求结果有序,且不想用额外空间,可以原地做,但排序会改变原数组) ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { sort(nums1.begin(), nums1.end()); sort(nums2.begin(), nums2.end()); vector<int> res; int i = 0, j = 0; while (i < nums1.size() && j < nums2.size()) { if (nums1[i] < nums2[j]) { i++; } else if (nums1[i] > nums2[j]) { j++; } else { // 确保结果中没有重复元素 if (res.empty() || nums1[i] != res.back()) { res.push_back(nums1[i]); } i++; j++; } } return res; } ``` 注意:以上两种方法都保证了结果中的元素唯一(即交集集合)。如果题目要求保留重复次数,则需要修改(例如使用unordered_map记录第一个数组中每个元素的出现次数,然后遍历第二个数组,每当遇到一个元素在map中存在且计数大于0,就添加到结果中并减少计数)。 但是,根据用户最初的问题,他要求的是相同元素(即交集),并没有明确要求保留重复次数。在引用[1]的Java代码中,它返回的是两个数组共同出现的元素,但不考虑重复次数(因为使用的是List的contains,而List允许重复,但在该代码中,第一个数组转化为List后,第二个数组遍历时遇到相同的就加入,所以如果第一个数组有重复,那么第二个数组中的相同元素会被重复添加)。然而,在引用[2]的leetcode题目中,要求返回的交集是唯一的。 因此,我们需要明确用户的需求。这里,我们按照返回唯一交集(即集合交集)来实现,这也是常见的需求。 如果用户希望保留重复次数,我们可以这样实现(使用哈希映射): ```cpp vector<int> intersect(vector<int>& nums1, vector<int>& nums2) { unordered_map<int, int> countMap; vector<int> res; // 遍历第一个数组,计数 for (int num : nums1) { countMap[num]++; } // 遍历第二个数组,如果元素在countMap中且计数大于0,则加入结果并减少计数 for (int num : nums2) { if (countMap.find(num) != countMap.end() && countMap[num] > 0) { res.push_back(num); countMap[num]--; } } return res; } ``` 但是,由于用户的问题描述是“提取两个数组相同元素”,我们可以理解为求交集(数学上的交集是集合,元素唯一),也可以理解为求公共元素(保留重复次数)。因此,我们需要根据实际情况选择。 考虑到用户提供的引用[1]中的Java代码返回的是重复元素(即如果一个元素在两个数组中出现多次,则会出现多次),而引用[2]中的leetcode题目要求唯一,这里我们提供两种版本,并说明区别。 总结: 1. 如果要求结果元素唯一(集合交集),使用上面的`intersection`方法(unordered_set或双指针)。 2. 如果要求保留重复次数(多重集交集),使用上面的`intersect`方法(哈希映射)。 现在,根据用户的问题,他之前提到的是“提取两个数组相同元素”,并且参考了引用[1]的Java代码,该代码返回的是所有相同的元素(包括重复的,因为第二个数组中的元素如果在第一个数组中出现一次,就会被加入一次,即使第一个数组有重复,但该代码并没有对第二个数组的重复做处理,所以如果第二个数组有重复而第一个数组没有,重复元素也会被加入)。实际上,该Java代码的结果中可能会出现重复元素,例如: a = [1,1,2,3], b = [1,1,2] 结果会是[1,1,2] 因此,我们可以理解为用户可能需要保留重复次数(即第二个数组中每个元素如果在第一个数组中出现,就加入一次,不管重复与否)。 为了明确,我们提供两种方法并解释: 版本1:返回所有相同的元素,保留重复次数(多重集交集) 版本2:返回唯一的相同元素(集合交集) 用户可以根据需要选择。 在C++中,更常见的是使用哈希映射来保留重复次数(即版本1)。 下面,我们给出一个完整的示例程序(使用版本1): ```cpp #include <iostream> #include <vector> #include <unordered_map> using namespace std; vector<int> getCommonElements(vector<int>& a, vector<int>& b) { unordered_map<int, int> countMap; vector<int> result; // 遍历数组a,计数 for (int num : a) { countMap[num]++; } // 遍历数组b,检查并添加到结果 for (int num : b) { if (countMap[num] > 0) { result.push_back(num); countMap[num]--; // 减少计数,确保每个元素在a中出现的次数被匹配一次 } } return result; } int main() { vector<int> a = {1, 2, 3, 4, 4, 5}; vector<int> b = {4, 4, 5, 6, 7}; vector<int> common = getCommonElements(a, b); cout << "Common elements: "; for (int num : common) { cout << num << " "; } cout << endl; return 0; } ``` 输出:Common elements: 4 4 5 注意:这个结果中,4出现了两次,因为数组a中有两个4,数组b中也有两个4,所以两个4都被匹配。而5只出现一次,因为a中只有一个5,b中也只有一个5。 如果用户希望结果唯一,则可以使用以下代码(使用unordered_set,同时避免重复添加): ```cpp vector<int> getCommonElementsUnique(vector<int>& a, vector<int>& b) { unordered_set<int> set(a.begin(), a.end()); vector<int> result; for (int num : b) { if (set.find(num) != set.end()) { result.push_back(num); set.erase(num); // 确保每个元素只被添加一次 } } return result; } ``` 同样的输入,输出:Common elements: 4 5 现在,用户可以根据需求选择合适的方法。 最后,我们生成相关问题: </think>### C++提取两个数组相同元素的实现方法 在C++中提取两个数组相同元素(即求交集)主要有两种高效方法: #### 1. **基于无序集合(HashSet)的查找法** 利用`unordered_set`的O(1)查找特性实现高效匹配: ```cpp #include <vector> #include <unordered_set> std::vector<int> findCommonElements( const std::vector<int>& arr1, const std::vector<int>& arr2 ) { std::unordered_set<int> set(arr1.begin(), arr1.end()); std::vector<int> result; for (int num : arr2) { if (set.find(num) != set.end()) { // O(1)查找 result.push_back(num); set.erase(num); // 避免重复添加 } } return result; } ``` **时间复杂度**:$O(m+n)$,其中$m$, $n$为数组长度[^2] **适用场景**:无需保持元素顺序时效率最高 #### 2. **排序+双指针法** 先排序再使用双指针同步遍历: ```cpp #include <vector> #include <algorithm> std::vector<int> findCommonElements( std::vector<int> arr1, std::vector<int> arr2 ) { std::sort(arr1.begin(), arr1.end()); // O(m log m) std::sort(arr2.begin(), arr2.end()); // O(n log n) std::vector<int> result; int i = 0, j = 0; while (i < arr1.size() && j < arr2.size()) { if (arr1[i] < arr2[j]) i++; else if (arr1[i] > arr2[j]) j++; else { result.push_back(arr1[i]); // 跳过重复元素(若需要唯一) while (i+1 < arr1.size() && arr1[i] == arr1[i+1]) i++; while (j+1 < arr2.size() && arr2[j] == arr2[j+1]) j++; i++; j++; } } return result; } ``` **时间复杂度**:$O(m \log m + n \log n)$ **适用场景**:需保持元素顺序或内存受限时[^1] #### 性能对比 | 方法 | 时间复杂度 | 空间复杂度 | 优势场景 | |--------------|------------------|------------|-------------------------| | HashSet法 | $O(m+n)$ | $O(m)$ | 随机数据,无需排序 | | 双指针法 | $O(m \log m + n \log n)$ | $O(1)$ | 有序数据,内存敏感 | > **选择建议**: > - 当数组无序且内存充足时优先使用HashSet法 > - 当数组已部分有序或需严格内存控制时使用双指针法 > - 若允许改变原数组,双指针法可原地操作[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值