游戏蛮牛学习群(纯技术交流,不闲聊):159852603
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

问答求助

关注:561

当前位置:游戏蛮牛 技术专区 问答求助

_____________________________________________________________________________________________________________
问答求助版块规则:

  1、问题尽量描述清楚
      2、代码要放在代码块里
      3、附件最好放到云盘,然后把链接放到TXT文档里,上传TXT文档。【最好没有附件,你懂得】
      4、本版块回复不得无意义,如:顶、呵呵、不错......以及擦边!【真的会扣分的哦】严重者,封IP!
      5、问题得到解决,请选择最佳答案。
      6、若问题是你自己解决了,可以联系管理员,返还蛮牛币,写下你的答案,另有蛮牛币奖赏。
_____________________________________________________________________________________________________________
查看: 956|回复: 23

[脚本] 如果 对一个链表同时做 插入和删除操作

[复制链接]  [移动端链接]
6蛮牛粉丝
1231/1500
排名
3477
昨日变化
2

46

主题

416

帖子

1231

积分

Rank: 6Rank: 6Rank: 6

UID
149133
好友
16
蛮牛币
866
威望
0
注册时间
2016-5-19
在线时间
360 小时
最后登录
2018-11-17
发表于 2018-11-5 15:01:45 | 显示全部楼层 |阅读模式
10蛮牛币
public List<Plate> plateList = new List<Plate>();  我创建一个 list 然后在update 里面不停的 插入和遍历数据,然后同时 不停的删除数据,  插入和删除的 速度不同,  这时候就会偶尔出现ArgumentOutOfRangeException: Argument is out of range.Parameter name: index  报错提示, 我的遍历方式是
for (int i = 0; i < plateList.Count; i++)
        {
            float dis = Vector2.Distance(plateList[i].pos, pos);
            if (dis <= posDistance)
            {
                return;
            }
        }

我理解是  在某一帧 遍历 时候, 恰好 plateList[i] 被删除了。 所有就出现报错 ,   哪位大佬说下 如何才能避免出错呀。 或者有什么好的方式 ,可以同时对一个链表 进行  插入,删除 和遍历操作。


回复

使用道具 举报

排名
790
昨日变化

17

主题

1148

帖子

3284

积分

Rank: 9Rank: 9Rank: 9

UID
68430
好友
13
蛮牛币
11872
威望
0
注册时间
2015-1-14
在线时间
889 小时
最后登录
2018-11-17
发表于 2018-11-5 15:01:46 | 显示全部楼层
两个方法粗略的写一下哈~~
方法1>
void update()
{
new 新列表 deleList;


for(你原本列表)
{
    if(执行条件满足)
       执行你的正经事情



    if(删除条件满足)
       deleList.add(条目);
}


for(便利deleList)
{
    原列表.remove(条目)
}
}
你看这样子,会产生越界吗?不会的~~


方法2> 利用MonoBehaviour生命周期 update 跟 lateupdate  执行差(非时间差哦,这仍然是同一帧)
void update()
{
for(你原本列表)
{
    if(执行条件满足)
       执行你的正经事情

}

}


void lateupdate ()
{
for(你原本列表)
{
    if(删除条件满足)
       原列表.remove(条目)

}

}



总结一下:方法1,利用临时列表暂时存储需要删除的条目,在执行正常循环完毕后,从原本列表内删除存储的条目,这样避免越界的
方法2,利用MonoBehaviour生命周期 update 跟 lateupdate  执行差,两个update 内各自执行一套相互不影响的循环,并执行将删除操作分割,这种方法也能避免越界~


希望能帮到你


点评

很强,赞!  发表于 2018-11-6 15:56

回复

使用道具 举报

5熟悉之中
695/1000
排名
3974
昨日变化
1

0

主题

29

帖子

695

积分

Rank: 5Rank: 5

UID
252114
好友
0
蛮牛币
640
威望
0
注册时间
2017-11-2
在线时间
302 小时
最后登录
2018-11-6
发表于 2018-11-5 15:55:29 | 显示全部楼层
遍历数组前,拿一个新列表用来遍历,遍历后更新这个新列表。保证此次遍历时列表长度不会有变化。或者写一个遍历方法,一个列表一旦开始遍历就不执行删除增加的操作,遍历完后调用删除增加的方法更新列表

回复

使用道具 举报

5熟悉之中
967/1000
排名
4037
昨日变化

5

主题

275

帖子

967

积分

Rank: 5Rank: 5

UID
234410
好友
2
蛮牛币
842
威望
0
注册时间
2017-7-26
在线时间
327 小时
最后登录
2018-11-15
发表于 2018-11-5 16:19:37 | 显示全部楼层
如果单纯的只是为了防止被删除影响数目 何不这样
int len = plateList.Count;
for (int i = 0; i < len ; i++)

回复

使用道具 举报

2初来乍到
103/150
排名
20643
昨日变化
4

0

主题

25

帖子

103

积分

Rank: 2Rank: 2

UID
143473
好友
0
蛮牛币
212
威望
0
注册时间
2016-3-25
在线时间
36 小时
最后登录
2018-11-7
发表于 2018-11-5 16:51:51 | 显示全部楼层
方法一:利用Unity脚本的生病周期进行List的增删遍历
方法二:遍历的时候判断一下当前i是否大于等于List的count,是return或break,否就继续;

回复

使用道具 举报

6蛮牛粉丝
1231/1500
排名
3477
昨日变化
2

46

主题

416

帖子

1231

积分

Rank: 6Rank: 6Rank: 6

UID
149133
好友
16
蛮牛币
866
威望
0
注册时间
2016-5-19
在线时间
360 小时
最后登录
2018-11-17
 楼主| 发表于 2018-11-5 19:42:50 | 显示全部楼层
随幻Kaller 发表于 2018-11-5 16:19
如果单纯的只是为了防止被删除影响数目 何不这样
int len = plateList.Count;
for (int i = 0; i < len ; i ...

正是因为数目是 删之前的, 所有导致遍历时候 删除,导致越界的

回复

使用道具 举报

6蛮牛粉丝
1231/1500
排名
3477
昨日变化
2

46

主题

416

帖子

1231

积分

Rank: 6Rank: 6Rank: 6

UID
149133
好友
16
蛮牛币
866
威望
0
注册时间
2016-5-19
在线时间
360 小时
最后登录
2018-11-17
 楼主| 发表于 2018-11-5 19:43:52 | 显示全部楼层
秋秋秋秋秋水 发表于 2018-11-5 15:55
遍历数组前,拿一个新列表用来遍历,遍历后更新这个新列表。保证此次遍历时列表长度不会有变化。或者写一个 ...

链表中的数组是根据时间自动删除的。 也就是链表中每个物体计时器到时间,自己删除,这个怎么控制
[发帖际遇]: 一个袋子砸在了 刘彦磊 头上,刘彦磊 赚了 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

6蛮牛粉丝
1231/1500
排名
3477
昨日变化
2

46

主题

416

帖子

1231

积分

Rank: 6Rank: 6Rank: 6

UID
149133
好友
16
蛮牛币
866
威望
0
注册时间
2016-5-19
在线时间
360 小时
最后登录
2018-11-17
 楼主| 发表于 2018-11-5 19:45:07 | 显示全部楼层
MaxSong 发表于 2018-11-5 16:51
方法一:利用Unity脚本的生病周期进行List的增删遍历
方法二:遍历的时候判断一下当前i是否大于等于List的c ...

你的第一种方法再详细解释下。 没明白

回复

使用道具 举报

6蛮牛粉丝
1231/1500
排名
3477
昨日变化
2

46

主题

416

帖子

1231

积分

Rank: 6Rank: 6Rank: 6

UID
149133
好友
16
蛮牛币
866
威望
0
注册时间
2016-5-19
在线时间
360 小时
最后登录
2018-11-17
 楼主| 发表于 2018-11-5 19:46:40 | 显示全部楼层
随幻Kaller 发表于 2018-11-5 16:19
如果单纯的只是为了防止被删除影响数目 何不这样
int len = plateList.Count;
for (int i = 0; i < len ; i ...

记录数量这个不行的。 因为我是在遍历过程中删除的数据,导致链表变化了。所以才越界的

回复

使用道具 举报

6蛮牛粉丝
1231/1500
排名
3477
昨日变化
2

46

主题

416

帖子

1231

积分

Rank: 6Rank: 6Rank: 6

UID
149133
好友
16
蛮牛币
866
威望
0
注册时间
2016-5-19
在线时间
360 小时
最后登录
2018-11-17
 楼主| 发表于 2018-11-5 19:48:40 | 显示全部楼层
MaxSong 发表于 2018-11-5 16:51
方法一:利用Unity脚本的生病周期进行List的增删遍历
方法二:遍历的时候判断一下当前i是否大于等于List的c ...

for (int j = 0; j < LastIdDic.Length; j++)
                    {
                          if(i>=LastIdDic.Count)
                              return;
                        if (LastIdDic[j]!=null)
                        {
                            if (LastIdDic[j].obj == plateObj)
                            {
                                LastIdDic[j] = null;
                            }
                        }                        
                    }

第二种方法是这样吗??

回复

使用道具 举报

7日久生情
1896/5000
排名
1800
昨日变化

19

主题

468

帖子

1896

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
218268
好友
5
蛮牛币
2152
威望
0
注册时间
2017-4-18
在线时间
693 小时
最后登录
2018-11-17

活力之星

发表于 2018-11-6 08:43:58 | 显示全部楼层
你可以试试while循环,做一个index时刻与count对比,超过了就跳出。不知道可以解决不

回复

使用道具 举报

5熟悉之中
967/1000
排名
4037
昨日变化

5

主题

275

帖子

967

积分

Rank: 5Rank: 5

UID
234410
好友
2
蛮牛币
842
威望
0
注册时间
2017-7-26
在线时间
327 小时
最后登录
2018-11-15
发表于 2018-11-6 09:24:42 | 显示全部楼层
刘彦磊 发表于 2018-11-5 19:46
记录数量这个不行的。 因为我是在遍历过程中删除的数据,导致链表变化了。所以才越界的 ...

这个不是链表 是列表
你可以将要删除的索引存起来 然后循环之后 统一从后往前删除
还有 在循环中删除本体本来就是不必要的 所以设计上也可以适当修改
[发帖际遇]: 随幻Kaller 发帖时在路边捡到 1 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复

使用道具 举报

5熟悉之中
695/1000
排名
3974
昨日变化
1

0

主题

29

帖子

695

积分

Rank: 5Rank: 5

UID
252114
好友
0
蛮牛币
640
威望
0
注册时间
2017-11-2
在线时间
302 小时
最后登录
2018-11-6
发表于 2018-11-6 09:28:48 | 显示全部楼层
我觉得每个物体计时器到时间,自己删除,然后同时还要一直遍历有点困难啊,可以统一写个每隔一段时间后先遍历,然后是增加删除的方法,就是每个物体自己的计时,如果到时间了,删掉然后更新等隔一段时间再从新遍历

回复

使用道具 举报

7日久生情
2764/5000
排名
586
昨日变化
4

2

主题

134

帖子

2764

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
121784
好友
0
蛮牛币
8851
威望
0
注册时间
2015-9-9
在线时间
1230 小时
最后登录
2018-11-18
发表于 2018-11-6 09:35:52 | 显示全部楼层
请使用ToArray将List转为数组(本质是复制操作),然后遍历这个数组

回复

使用道具 举报

5熟悉之中
957/1000
排名
13503
昨日变化
2

5

主题

190

帖子

957

积分

Rank: 5Rank: 5

UID
26011
好友
0
蛮牛币
1328
威望
0
注册时间
2014-5-21
在线时间
698 小时
最后登录
2018-11-16
发表于 2018-11-6 11:31:43 | 显示全部楼层
多线程。lock锁。一个线程删,一个线程增。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

关闭

站长推荐 上一条 /1 下一条

快速回复 返回顶部 返回列表