【问题标题】:Accessing unique array by name按名称访问唯一数组
【发布时间】:2017-10-09 22:02:02
【问题描述】:

我有一组像这样的整数数组-

public int[] box1 = {1, 0, 2};
public int[] box2 = {3, 1, 0};
public int[] box3 = {2, 3, 1};

我需要做的是通过唯一的数组名称动态访问它们,并从中返回一个随机元素,使用类似这样的东西-

foo="box"+2[random int];

其中 foo 是我的临时字符串,包括“box”前缀,将我想要的数字添加到“box”,并从“box2”中获取一个随机元素。 (例如:foo=3)

如果我通过字符串方法执行此操作,它会创建正确的命名法,但它只是一个字符串,我不能使用它在脚本中实际访问这些作为实际的类/数组元素并将它们传递给其他东西。

我该怎么做呢?阅读手册几个小时,尝试了列表,但我认为我做的不对。谢谢!

【问题讨论】:

  • 您正在寻找Dictionary
  • 不是Dictionary,而是Lookup
  • 不是DictionaryLookup,而是带有indexer 的自定义类
  • 或数组数组:box[2][random int];
  • 我决定用Dictionary 留下答案,因为没有人留下满足您问题语法的答案。希望能解决问题。

标签: c# arrays unity3d


【解决方案1】:

只需分解您真正想做的事情,您就会发现它是多么容易。就像我在评论部分提到的Dictionary 一样,您仍然需要另外两个 C# 功能来完成确切的语法。

你希望能够做到这一点:

foo="box"+2[random int];

与此相同:

int valueFromArray  = arrayVariableName [index];

在下面的示例中,我们可以假设 MyScript 是我们脚本的名称。

1。你需要一个可以保存名字和int数组的字典。

Dictionary<string, int[]> boxes

2。您需要一种将 "box"+2arrayVariableName 转换为当前脚本实例的方法。这可以通过 C# 中的隐式转换运算符功能来完成。您可以将 "box"+2arrayVariableName 传递到这个隐式 MyScript 中,然后将其存储到全局变量中以供下一步使用。

//The global variable that holds the arrayVariableName to access
static string targetBox = null;

//Implicit conversion operators (box array name to this script(MyScript) instance)
public static implicit operator MyScript(string box)
{
    return setTargetAndGetInstance(box);
}

public static MyScript setTargetAndGetInstance(string box)
{
    if (instance.boxes.ContainsKey(box))
    {
        //Set the box requested. This will be needed in the Indexer overloading above
        targetBox = box;
        return instance;
    }
    else
        return null;
}

3。现在,您可以实现 [index] 语法。这可以通过索引器重载功能来实现。

//Indexer overloading (index to int (value in array))
public int this[int index]
{
    get
    {
        //Get value based on value set in the implicit operators
        return accessBox(targetBox, index);
    }
}

现在,当你这样做时,"box"+2,它将在 implicit 转换运算符的帮助下返回 this(MyScript) 的实例。然后它将允许您使用索引器重载功能执行 [random int]


下面的代码是您问题中的语法示例以及执行此操作的其他类似方法。 包括类似的,因为它们看起来比您要求的更好

用一个简单的功能:

int test1 = accessBox("box" + 2, UnityEngine.Random.Range(0, 3));
Debug.Log(test1);

使用arrayVariableName [index] 语法:

你正在寻找这个,但 MyScript 的转换看起来很糟糕

int test2 = ((MyScript)("box" + 2))[UnityEngine.Random.Range(0, 3)];
Debug.Log(test2);

使用[arrayVariableName][index] 语法:

int test3 = this["box" + 2][UnityEngine.Random.Range(0, 3)];
Debug.Log(test3);

使用[arrayVariableName, index] 语法

int test4 = this["box" + 2, UnityEngine.Random.Range(0, 3)];
Debug.Log(test4);

完整的功能示例:

using System.Collections.Generic;
using UnityEngine;

public class MyScript : MonoBehaviour
{

    public int[] box1 = { 1, 0, 2 };
    public int[] box2 = { 3, 1, 0 };
    public int[] box3 = { 2, 3, 1 };


    public Dictionary<string, int[]> boxes = new Dictionary<string, int[]>();
    private static MyScript instance;

    void Awake()
    {
        instance = this;

        //Add to Dictionary
        addBox();

        int test1 = accessBox("box" + 2, UnityEngine.Random.Range(0, 3));
        Debug.Log(test1);

        int test2 = ((MyScript)("box" + 2))[UnityEngine.Random.Range(0, 3)];
        Debug.Log(test2);

        int test3 = this["box" + 2][UnityEngine.Random.Range(0, 3)];
        Debug.Log(test3);

        int test4 = this["box" + 2, UnityEngine.Random.Range(0, 3)];
        Debug.Log(test4);
    }

    void addBox()
    {
        boxes.Add("box1", box1);
        boxes.Add("box2", box2);
        boxes.Add("box3", box3);
    }

    public int accessBox(string box, int index)
    {
        //Return the array from the Dictionary
        int[] tempVar;
        if (boxes.TryGetValue(box, out tempVar))
        {
            //Return the spicified index
            return tempVar[index];
        }
        else
        {
            //ERROR - return -1
            return -1;
        }
    }


    //Indexer overloading (index to int (value in array))
    public int this[int index]
    {
        get
        {
            //Get value based on value set in the implicit operators
            return accessBox(targetBox, index);
        }
    }

    static string targetBox = null;

    //Implicit conversion operators (box array name to this script(MyScript) instance)
    public static implicit operator MyScript(string box)
    {
        return setTargetAndGetInstance(box);
    }

    public static MyScript setTargetAndGetInstance(string box)
    {
        if (instance.boxes.ContainsKey(box))
        {
            //Set the box requested. This will be needed in the Indexer overloading above
            targetBox = box;
            return instance;
        }
        else
            return null;
    }

    //Indexer overloading (box array name to this script(MyScript) instance)
    public MyScript this[string box]
    {
        get
        {
            return setTargetAndGetInstance(box);
        }
    }

    //Indexer overloading (box array name to int)
    public int this[string box, int index]
    {
        get
        {
            setTargetAndGetInstance(box);
            return accessBox(box, index);
        }
    }
}

【讨论】:

    【解决方案2】:

    这是您的问题的通用解决方案,使用 Dictionary&lt;TKey,TValue&gt;

    主要代码:

    using System;
    using System.Collections.Generic;
    
    public class Class1
    {
        public void Example()
        {
            // a dictionary with string keys
    
            var string1 = "abcd";
            var string2 = "efgh";
    
            var dictionary1 = new Dictionary<string, int[]>
            {
                {string1, new[] {0, 1, 2}},
                {string2, new[] {3, 4, 5}}
            };
    
    
            // a dictionary with custom type
    
            var box1 = new Box(10, 10);
            var box2 = new Box(20, 20);
    
            var dictionary2 = new Dictionary<Box, int[]>
            {
                {box1, new[] {0, 1, 2}},
                {box2, new[] {3, 4, 5}}
            };
    
            // get random value from both dictionnaries
    
            var i1 = GetRandomInteger(dictionary1, string1);
            var i2 = GetRandomInteger(dictionary2, box1);
        }
    
        private int GetRandomInteger<TKey>(IDictionary<TKey, int[]> dictionary, TKey key)
        {
            if (!dictionary.ContainsKey(key))
                throw new KeyNotFoundException();
    
            var array = dictionary[key];
    
            // prefer UnityEngine.Random here since it's static 
            var index = new Random().Next(array.Length);
    
            var value = array[index];
    
            return value;
        }
    }
    

    额外代码:

    public struct Box
    {
        // a dictionary key should be immutable, therefore I use a struct
        // implement equality members so that when querying the dictionary,
        // it will find the value associated to the key
        // see https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type
    
        public int Width { get; }
        public int Height { get; }
    
        public Box(int width, int height)
        {
            Width = width;
            Height = height;
        }
    
        public bool Equals(Box other)
        {
            return Width == other.Width && Height == other.Height;
        }
    
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
                return false;
            return obj is Box && Equals((Box) obj);
        }
    
        public override int GetHashCode()
        {
            unchecked
            {
                return (Width * 397) ^ Height;
            }
        }
    
        public static bool operator ==(Box left, Box right)
        {
            return left.Equals(right);
        }
    
        public static bool operator !=(Box left, Box right)
        {
            return !left.Equals(right);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-22
      • 1970-01-01
      • 1970-01-01
      • 2013-01-02
      • 1970-01-01
      • 1970-01-01
      • 2015-06-23
      • 1970-01-01
      相关资源
      最近更新 更多