按名称访问唯一数组
Posted
技术标签:
【中文标题】按名称访问唯一数组【英文标题】: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
不是Dictionary
或Lookup
,而是带有indexer
的自定义类
或数组数组:box[2][random int];
我决定用Dictionary
留下答案,因为没有人留下满足您问题语法的答案。希望能解决问题。
【参考方案1】:
只需分解您真正想做的事情,您就会发现它是多么容易。就像我在评论部分提到的Dictionary
一样,您仍然需要另外两个 C# 功能来完成确切的语法。
你希望能够做到这一点:
foo="box"+2[random int];
与此相同:
int valueFromArray = arrayVariableName [index];
在下面的示例中,我们可以假设 MyScript
是我们脚本的名称。
1。你需要一个可以保存名字和int数组的字典。
Dictionary<string, int[]> boxes
2。您需要一种将 "box"+2
或 arrayVariableName
转换为当前脚本实例的方法。这可以通过 C# 中的隐式转换运算符功能来完成。您可以将 "box"+2
或 arrayVariableName
传递到这个隐式 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<TKey,TValue>
:
主要代码:
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);
【讨论】:
以上是关于按名称访问唯一数组的主要内容,如果未能解决你的问题,请参考以下文章
SQL JSON PATH 如何在从较大的 json 集中提取后按索引访问 json 数组