iOS中如何按指定起始位置与间隔向二维数组插入元素?
我来帮你拆解这个问题,其实核心逻辑没那么复杂——二维数组的插入规则是基于全局元素的连续计数来判断时机的,不是每个子数组单独处理。结合你给的示例和定义,我把具体步骤和适配iOS场景的代码整理如下:
一、先理清楚规则细节
根据你的定义:
startPosition:第一个要插入的位置(按全局元素顺序从0开始数)interval:两次插入之间要跳过的原元素数量(比如第一次插完后,再数interval个原元素,就进行下一次插入)
拿你的示例验证:原二维数组的全局元素流是[1,2,3,4,5,6,7,8],startPosition=1、interval=3的话,插入位置就是1、4、7,对应到二维数组里就是在1之后、4之后、7之后插入a,和你给出的结果完全匹配。
二、通用实现(Objective-C代码)
1. 先算出所有需要插入的全局位置
首先我们得先把所有要插入的位置算出来,避免遍历的时候反复判断:
// 原二维数组 NSArray *originalArray = @[@[@1,@2,@3], @[@4,@5], @[@6,@7,@8]]; // 先算原数组总共有多少个元素 NSInteger totalElementCount = 0; for (NSArray *subArray in originalArray) { totalElementCount += subArray.count; } NSInteger startPosition = 1; NSInteger interval = 3; NSMutableArray *insertPositions = [NSMutableArray array]; // 生成所有插入位置 NSInteger currentPos = startPosition; while (currentPos <= totalElementCount) { [insertPositions addObject:@(currentPos)]; currentPos += interval; }
这里注意:如果currentPos等于总元素数,意味着要在最后一个元素后面插入。
2. 遍历原数组,插入自定义值a
接下来我们遍历每个子数组,同时维护一个全局计数器,碰到插入位置就把a加进去:
// 这里可以换成任意值,甚至每个a不一样 NSArray *customValues = @[@"a1", @"a2", @"a3", @"a4"]; NSMutableArray *resultArray = [NSMutableArray array]; NSInteger globalCounter = 0; NSInteger insertIndex = 0; for (NSArray *subArray in originalArray) { NSMutableArray *newSubArray = [NSMutableArray array]; for (id element in subArray) { // 先检查当前位置是不是要插入的点 if (insertIndex < insertPositions.count && [insertPositions[insertIndex] integerValue] == globalCounter) { [newSubArray addObject:customValues[insertIndex]]; insertIndex++; } // 加入原元素 [newSubArray addObject:element]; globalCounter++; } // 子数组遍历完后,检查要不要在末尾插a(比如刚好到全局计数的插入点) while (insertIndex < insertPositions.count && [insertPositions[insertIndex] integerValue] == globalCounter) { [newSubArray addObject:customValues[insertIndex]]; insertIndex++; globalCounter++; } [resultArray addObject:newSubArray]; }
运行这段代码后,resultArray就会得到你要的结果:[[1,a1,2,3,a2], [4,5,a3], [6,7,a4,8]](如果用统一的@"a"就是你示例里的样子)。
三、适配iOS Mobup SDK多分区TableView插原生广告
这个逻辑直接对应多分区TableView的广告插入需求:
- 二维数组的每个子数组 → TableView的一个
section - 子数组的每个元素 → section里的一个正常
row - 插入的
a→ 广告cell
关键适配步骤:
1. 计算每个section的实际row数
在tableView:numberOfRowsInSection:里,要算出原section的元素数加上该section里要插的广告数量:
// 提前算好的广告全局位置数组 NSArray *adPositions = ...; - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSArray *originalSectionData = self.originalData[section]; // 先算这个section在全局计数里的起始和结束位置 NSInteger sectionStartGlobalIndex = 0; for (NSInteger i=0; i<section; i++) { sectionStartGlobalIndex += self.originalData[i].count; } NSInteger sectionEndGlobalIndex = sectionStartGlobalIndex + originalSectionData.count; // 统计这个section里有多少个广告位 NSInteger adCount = 0; for (NSNumber *pos in adPositions) { NSInteger position = [pos integerValue]; if (position >= sectionStartGlobalIndex && position < sectionEndGlobalIndex) { adCount++; } } // 检查是不是有广告在section末尾 if ([adPositions containsObject:@(sectionEndGlobalIndex)]) { adCount++; } return originalSectionData.count + adCount; }
2. 判断当前row是广告还是正常内容
在tableView:cellForRowAtIndexPath:里,要判断当前row对应的是不是广告位,是的话就加载Mobup的广告cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 先算当前section在全局计数里的起始位置 NSInteger sectionStartGlobalIndex = 0; for (NSInteger i=0; i<indexPath.section; i++) { sectionStartGlobalIndex += self.originalData[i].count; } // 算出当前row对应的原数据位置(要减去前面的广告数量) NSInteger adsBeforeThisRow = 0; for (NSNumber *pos in adPositions) { NSInteger posValue = [pos integerValue]; if (posValue < sectionStartGlobalIndex + indexPath.row - adsBeforeThisRow) { adsBeforeThisRow++; } } NSInteger originalRow = indexPath.row - adsBeforeThisRow; // 判断是不是广告位 if ([adPositions containsObject:@(sectionStartGlobalIndex + originalRow)]) { // 加载Mobup原生广告cell MobupNativeAdCell *adCell = [tableView dequeueReusableCellWithIdentifier:@"MobupAdCell" forIndexPath:indexPath]; // 这里配置广告内容,比如调用Mobup SDK的加载方法 [self loadMobupAdIntoCell:adCell]; return adCell; } else { // 加载正常内容cell NormalContentCell *normalCell = [tableView dequeueReusableCellWithIdentifier:@"NormalContentCell" forIndexPath:indexPath]; normalCell.data = self.originalData[indexPath.section][originalRow]; return normalCell; } }
四、小技巧:每个广告可以不一样
如果需要每个插入的广告(或a)是不同的内容,只需要把customValues换成广告数据数组,插入的时候按insertIndex取对应的广告内容就行,完全适配Mobup SDK的多广告位需求。
内容的提问来源于stack exchange,提问作者Vyachaslav Gerchicov

