【问题标题】:Array index out of range when filling a Dictionary using text.Split使用 text.Split 填充字典时数组索引超出范围
【发布时间】:2016-08-13 19:56:22
【问题描述】:

基本上,我正在尝试使用 TextAsset 填充字典,但在此过程中,我不断收到“IndexOutOfRangeException:数组索引超出范围”。来自其中一个阵列,我不知道为什么......我在 Unity 5 中使用 Visual Studio 社区,而且,我只是在 4 个月前才开始学习编程,老实说不知道可能是什么问题。 ..

public Dictionary<string, string> Items = new Dictionary<string, string>();

Start(){
var itemList = Resources.Load("ItemList", typeof(TextAsset)) as TextAsset;

        //populating the Dictionaries using previous text assets. Line by Line. 
        //Populating Dictionary with Text Asset with format Item:Id. The ':' symbol separates lines into columns
        string[] rows = itemList.text.Split('\n');
        foreach (string row in rows)
        {
            string[] data = row.Split(':');
            Items.Add(data[0].Trim(), data[1].Trim()); //exception is thrown in this line
        }
}

ItemList.txt 有这些测试行:

Health Potion:1
Mana potion:2
Beet:3
Poisonous Beet:4
Cheese Slice:5

另一件事是,Visual Studio 一直在 text.Split 行中用波浪线在 itemList (TextAsset) 下划线并显示工具提示:可能的 System.NullReferenceException。但是 unity 根本没有显示任何关于 null 引用的错误。

无论如何,任何建议都将不胜感激。

【问题讨论】:

  • 在调试器中抛出异常的行放置一个断点并运行您的应用程序。我敢打赌data 的元素少于 2 个。这是因为至少一个row 不包含:。在调试器中查看itemList 的内容。
  • 嘿,谢谢!没想到这么简单,因为最后有一个空行!但是,无论如何,有没有办法解决这个问题?让代码忽略空行?猜猜,我得去论坛看看,否则我会因为“背负式”问题而被骂。无论如何,谢谢。

标签: c# arrays dictionary split


【解决方案1】:

使用这个:

public Dictionary<string, int> Items = new Dictionary<string, int>();
...
string[] rows = itemList.text.Split('\n');
foreach (string row in rows)
{
    string[] data = row.Split(':');
    int i;
    if (data.Length > 1 && int.TryParse(data[1].Trim(), out i))
        Items.Add(data[0].Trim(), i);
}

【讨论】:

  • 太好了,我会同时使用这两个建议!
  • 哦,不过,只有一件事,项目名称旁边的数字并不能完全代表实际数字...实际数字将是 Id 数字指向到第三方资产(Unity Asset Adventure 创建者)中创建的一些全局变量,因此它们不太可能是有序的。我将如何调整代码?我还没有尝试过,但它给我的印象是代码是为了按出现顺序排列单词(这是我之前没有提到的错误)。
  • 数字不需要是为了让这个代码工作。但是,当您说“身份证号码”时,我怀疑 Items 应该是 new Dictionary&lt;int, string&gt;(),您应该使用 Items.Add(i, data[0].Trim())
  • 此外,“项目”是一个含糊且具有误导性的名称。如果这些东西是“第三方资产”,那么Assets 将是一个更好的名称。
  • 感谢您的澄清,我稍后再试。字典的问题是我稍后要合并两个字典,一个有项目和 ID,另一个有一个名称列表()。我的目的是验证目标/情况(物品使用、具体行动或到达某个位置)。如果满足要求,奖励玩家(物品或金钱)并切换到其他目标,但我需要一个主列表来验证分配什么(并连续两次避免相同的目标)。对于物品奖励,我计划使用解析将 dic.value 转换为 int。无论如何,这就是为什么 dict 是 .
【解决方案2】:

您的数据中可能有额外的空元素,因此当您调用 Split 时,请使用带有第二个参数的重载:

string[] rows = itemList.text.Split('\n', StringSplitOptions.RemoveEmptyEntries);

这将删除数据中的所有空行

string[] data = row.Split(':', StringSplitOptions.RemoveEmptyEntries);

这将删除冒号前后没有任何内容的任何情况。

在尝试寻址元素之前,您还应该检查生成的 data 数组的长度是否为 2:

if (data.Length == 2)
{
    Items.Add(data[0].Trim(), data[1].Trim());
}
else
{
    // Deal with the error - could be as simple as ignoring it or logging the dodgy data
}

那么数据将是您所期望的。

【讨论】:

  • 请注意,如果行非空但不包含':',这仍然会抛出NullReferenceException
  • @DourHighArch 真实。
猜你喜欢
  • 1970-01-01
  • 2020-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 2015-01-24
  • 2016-03-29
  • 1970-01-01
相关资源
最近更新 更多