yield IEnumerable
Добавлено: 23 июн 2014, 18:58
Тут небольшая фишка C#, достаточно полезная, если понимать, что происходит.
Вкратце, когда Вам нужен набор рандомных чисел, обычно все создают лист\массив и набивают его рандомными значениями, но можно поступить попроще.
Это подходит и не только для рандомных чисел, но и для последовательности значений вычисляемых по какой-то формуле.
Например, чтобы получить набор рандомных float, достаточно объявить такой метод
и использовать его так
ниже пример с рандомными флоатами, рандомными векторами и числами фибоначи
Вкратце, когда Вам нужен набор рандомных чисел, обычно все создают лист\массив и набивают его рандомными значениями, но можно поступить попроще.
Это подходит и не только для рандомных чисел, но и для последовательности значений вычисляемых по какой-то формуле.
Например, чтобы получить набор рандомных float, достаточно объявить такой метод
Синтаксис:
Используется csharp
private IEnumerable<float> RangeFloat(float min, float max, int count)
{
for (var i = 0; i < count; i++)
yield return Random.Range(min, max);
}
{
for (var i = 0; i < count; i++)
yield return Random.Range(min, max);
}
и использовать его так
Синтаксис:
Используется csharp
foreach (var f in RangeFloat(min: 0f, max: 10f, count: 10))
print(f);
print(f);
ниже пример с рандомными флоатами, рандомными векторами и числами фибоначи
Синтаксис:
Используется csharp
using System.Collections.Generic;
using UnityEngine;
using Func = System.Func<float, float, float>;
public class TestIEnumerable : MonoBehaviour
{
private void Awake()
{
const int countFloat = 10, countFib = 10, countVector = 10;
print("Float Random Range " + countFloat);
foreach (var f in RangeFloat(min: 0f, max: 10f, count: countFloat))
{
print(f);
}
print("Fibonacci Range " + countFib);
foreach (var f in RangeFibonacci(count: countFib))
{
print(f);
}
print("Vector3 Random Range " + countVector);
foreach (var v in RangeVector3(min: Vector3.zero, max: Vector3.one * 10f, count: countVector))
{
var go = GameObject.CreatePrimitive(PrimitiveType.Cube);
go.transform.position = v;
print(v);
}
}
private Func random = Random.Range;
private IEnumerable<float> RangeFloat(float min, float max, int count)
{
for (var i = 0; i < count; i++)
yield return random(min, max);
}
private IEnumerable<int> RangeFibonacci(short count)
{
for (short i = 1; i < count; i++)
yield return Fibonacci.Calculate(i);
}
private IEnumerable<Vector3> RangeVector3(Vector3 min, Vector3 max, int count)
{
for (var i = 0; i < count; i++)
yield return new Vector3(random(min.x, max.x), random(min.y, max.y), random(min.z, max.z));
}
private static class Fibonacci
{
private static readonly Matrix2 FibMtx = new Matrix2 { OneOne = 1, OneTwo = 1, TwoOne = 1 };
private static readonly Matrix2 Identity = new Matrix2 { OneOne = 1, TwoTwo = 1 };
private struct Matrix2
{
public int OneOne, OneTwo, TwoOne, TwoTwo;
public static Matrix2 operator *(Matrix2 lhs, Matrix2 rhs)
{
return new Matrix2
{
OneOne = lhs.OneOne * rhs.OneOne + lhs.OneTwo * rhs.TwoOne,
OneTwo = lhs.OneOne * rhs.OneTwo + lhs.OneTwo * rhs.TwoTwo,
TwoOne = lhs.TwoOne * rhs.OneOne + lhs.TwoTwo * rhs.TwoOne,
TwoTwo = lhs.TwoOne * rhs.OneTwo + lhs.TwoTwo * rhs.TwoTwo
};
}
}
private static Matrix2 MatrixPower(Matrix2 x, short power)
{
if (power == 0) return Identity;
if (power == 1) return x;
int n = 15;
while ((power <<= 1) >= 0) n--;
Matrix2 tmp = x;
while (--n > 0)
tmp = (tmp * tmp) * (((power <<= 1) < 0) ? x : Identity);
return tmp;
}
public static int Calculate(short n)
{
return MatrixPower(FibMtx, (short)(n - 1)).OneOne;
}
}
}
using UnityEngine;
using Func = System.Func<float, float, float>;
public class TestIEnumerable : MonoBehaviour
{
private void Awake()
{
const int countFloat = 10, countFib = 10, countVector = 10;
print("Float Random Range " + countFloat);
foreach (var f in RangeFloat(min: 0f, max: 10f, count: countFloat))
{
print(f);
}
print("Fibonacci Range " + countFib);
foreach (var f in RangeFibonacci(count: countFib))
{
print(f);
}
print("Vector3 Random Range " + countVector);
foreach (var v in RangeVector3(min: Vector3.zero, max: Vector3.one * 10f, count: countVector))
{
var go = GameObject.CreatePrimitive(PrimitiveType.Cube);
go.transform.position = v;
print(v);
}
}
private Func random = Random.Range;
private IEnumerable<float> RangeFloat(float min, float max, int count)
{
for (var i = 0; i < count; i++)
yield return random(min, max);
}
private IEnumerable<int> RangeFibonacci(short count)
{
for (short i = 1; i < count; i++)
yield return Fibonacci.Calculate(i);
}
private IEnumerable<Vector3> RangeVector3(Vector3 min, Vector3 max, int count)
{
for (var i = 0; i < count; i++)
yield return new Vector3(random(min.x, max.x), random(min.y, max.y), random(min.z, max.z));
}
private static class Fibonacci
{
private static readonly Matrix2 FibMtx = new Matrix2 { OneOne = 1, OneTwo = 1, TwoOne = 1 };
private static readonly Matrix2 Identity = new Matrix2 { OneOne = 1, TwoTwo = 1 };
private struct Matrix2
{
public int OneOne, OneTwo, TwoOne, TwoTwo;
public static Matrix2 operator *(Matrix2 lhs, Matrix2 rhs)
{
return new Matrix2
{
OneOne = lhs.OneOne * rhs.OneOne + lhs.OneTwo * rhs.TwoOne,
OneTwo = lhs.OneOne * rhs.OneTwo + lhs.OneTwo * rhs.TwoTwo,
TwoOne = lhs.TwoOne * rhs.OneOne + lhs.TwoTwo * rhs.TwoOne,
TwoTwo = lhs.TwoOne * rhs.OneTwo + lhs.TwoTwo * rhs.TwoTwo
};
}
}
private static Matrix2 MatrixPower(Matrix2 x, short power)
{
if (power == 0) return Identity;
if (power == 1) return x;
int n = 15;
while ((power <<= 1) >= 0) n--;
Matrix2 tmp = x;
while (--n > 0)
tmp = (tmp * tmp) * (((power <<= 1) < 0) ? x : Identity);
return tmp;
}
public static int Calculate(short n)
{
return MatrixPower(FibMtx, (short)(n - 1)).OneOne;
}
}
}