I have this line of code and I want under certain conditions to initialize the whole array to true in one line,
How can I do that?
public bool[,] OptionalHours { get; set; } = new bool[6, 24];
Technically, this would do it:
for(int i = 0, x = _optionalHours.GetLength(0), y = _optionalHours.GetLength(1); i < x * y; _optionalHours[i/y, i%y] = true, i++);
It gets shorter if you're happy to fix the 6 and 24 and jiggle some ops around:
for(int i = 6*24; --i >= 0; _optionalHours[i/24, i%24] = true);
Would you use it though? Well; could you understand it immediately and are happy to explain it to anyone else who asks? If yes, then use it. If no then go for something more expected:
for(int x = _optionalHours.GetUpperBound(0); x >= 0; x--)
for(int y = _optionalHours.GetUpperBound(1); y >= 0; y--)
_optionalHours[x, y] = true;
There aren't any prizes at code review for the person who wrote the most WTF..
It's also quite a small array (hours in a week?) so you could also init it with this one-liner that's easier to figure:
var _optionalHours = new[,]{
{true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true},
{true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true},
{true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true},
{true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true},
{true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true},
{true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true}
};
As an idle curiosity, you could also do it "mathematically", wrap the array in a class that will invert the bools if some condition is set:
public class SixByTwentyFour
{
private bool[,] _optionalHours { get; set; } = new bool[6, 24];
public bool CertainCondition;
public bool this[int x, int y]{
get => _optionalHours[x,y] ^ CertainCondition;
set { _optionalHours[x,y] = value ^ CertainCondition; }
}
}
You can access an instance of this class as though it were a 2D array:
var sbtf = new SixByTwentyFour();
sbtf.CertainCondition = true;
Console.WriteLine(sbtf[1,1]); //prints true
This one doesn't give you a "Properties should not return arrays" warning if you have an analayzer enabled that looks for such :D
https://simmer.io/#JammerLamma/~c09dd45e-0528-01ce-e641-e4a56fb9cfed
https://github.com/JammerLamma/Number-Muncher-Clone
I'm creating a number munchers clone, and the integer variables are not getting properly assigned. It works for a few games, but after a few times of winning, and/or clicking quit, and choosing another game it appears the for loop goes through properly. The game says there are 5 maxCorrect, and correctOnBoard is also set to 5, so I assume the loop goes through 5 times, however, only 4 tiles get set as correct, then sometimes 2, or 4, but never 5 again. It always works as intended the first game.
If I comment out //AssignRest(); the problem still persists.
public void GenerateEven()
{
//GameObject smasher = Instantiate(smasherPF, transform.position, transform.rotation);
remainingNumbers = totalTiles - maxCorrect;
GetLists();
GetTiles();
AssignEven();
RemoveDuplicates(evenNumbers);
AssignRest();
}
private void AssignEven()
{
int maxCorrect = 5;
for (int i = 1; i <= maxCorrect; i++)
{
randomChild = children[UnityEngine.Random.Range(0, children.Count)];
int maxLength = evenNumbers.Count;
int tempTileNum = evenNumbers[UnityEngine.Random.Range(0, maxLength)];
randomChild.GetComponent<Tile>()._TileNumber = tempTileNum;
randomChild.GetComponent<Tile>()._IsCorrect = true;
correctOnBoard++;
randomChild.GetComponent<SpriteRenderer>().sprite = numberSprite[tempTileNum - 1];
Debug.Log(tempTileNum);
}
}
Some things are serialized for debugging purposes. All of the lists get generated correctly.
Changed the code to
private void AssignEven()
{
for (int i = 1; i <= maxCorrect;)
{
randomChild = children[UnityEngine.Random.Range(0, children.Count)];
if(randomChild.GetComponent<Tile>()._IsCorrect == false)
{
int maxLength = evenNumbers.Count;
int tempTileNum = evenNumbers[UnityEngine.Random.Range(0, maxLength)];
randomChild.GetComponent<Tile>()._TileNumber = tempTileNum;
randomChild.GetComponent<Tile>()._IsCorrect = true;
correctOnBoard++;
randomChild.GetComponent<SpriteRenderer>().sprite = numberSprite[tempTileNum - 1];
Debug.Log(tempTileNum);
i++;
}
}
}
Thanks to John Wu!
im frenchi so sorry first sorry for my english .
I have an error on visual studio (index out of range) i have this problem only with a Parallel.For not with classic for.
I think one thread want acces on my array[i] and another thread want too ..
It's a code for calcul Kmeans clustering for building link between document (with cosine similarity).
more information :
IndexOutOfRange is on similarityMeasure[i]=.....
I have a computer with 2 Processor (12logical)
with classic for , cpu usage is 9-14% , time for 1 iteration=9min..
with parallel.for , cpu usage is 70-90% =p, time for 1 iteration =~1min30
Sometimes it works longer before generating an error
My function is :
private static int FindClosestClusterCenter(List<Centroid> clustercenter, DocumentVector obj)
{
float[] similarityMeasure = new float[clustercenter.Count()];
float[] copy = similarityMeasure;
object sync = new Object();
Parallel.For(0, clustercenter.Count(), (i) => //for(int i = 0; i < clustercenter.Count(); i++) Parallel.For(0, clustercenter.Count(), (i) => //
{
similarityMeasure[i] = SimilarityMatrics.FindCosineSimilarity(clustercenter[i].GroupedDocument[0].VectorSpace, obj.VectorSpace);
});
int index = 0;
float maxValue = similarityMeasure[0];
for (int i = 0; i < similarityMeasure.Count(); i++)
{
if (similarityMeasure[i] > maxValue)
{
maxValue = similarityMeasure[i];
index = i;
}
}
return index;
}
My function is call here :
do
{
prevClusterCenter = centroidCollection;
DateTime starttime = DateTime.Now;
foreach (DocumentVector obj in documentCollection)//Parallel.ForEach(documentCollection, parallelOptions, obj =>//foreach (DocumentVector obj in documentCollection)
{
int ind = FindClosestClusterCenter(centroidCollection, obj);
resultSet[ind].GroupedDocument.Add(obj);
}
TimeSpan tempsecoule = DateTime.Now.Subtract(starttime);
Console.WriteLine(tempsecoule);
//Console.ReadKey();
InitializeClusterCentroid(out centroidCollection, centroidCollection.Count());
centroidCollection = CalculMeanPoints(resultSet);
stoppingCriteria = CheckStoppingCriteria(prevClusterCenter, centroidCollection);
if (!stoppingCriteria)
{
//initialisation du resultat pour la prochaine itération
InitializeClusterCentroid(out resultSet, centroidCollection.Count);
}
} while (stoppingCriteria == false);
_counter = counter;
return resultSet;
FindCosSimilarity :
public static float FindCosineSimilarity(float[] vecA, float[] vecB)
{
var dotProduct = DotProduct(vecA, vecB);
var magnitudeOfA = Magnitude(vecA);
var magnitudeOfB = Magnitude(vecB);
float result = dotProduct / (float)Math.Pow((magnitudeOfA * magnitudeOfB),2);
//when 0 is divided by 0 it shows result NaN so return 0 in such case.
if (float.IsNaN(result))
return 0;
else
return (float)result;
}
CalculMeansPoint :
private static List<Centroid> CalculMeanPoints(List<Centroid> _clust)
{
for (int i = 0; i < _clust.Count(); i++)
{
if (_clust[i].GroupedDocument.Count() > 0)
{
for (int j = 0; j < _clust[i].GroupedDocument[0].VectorSpace.Count(); j++)
{
float total = 0;
foreach (DocumentVector vspace in _clust[i].GroupedDocument)
{
total += vspace.VectorSpace[j];
}
_clust[i].GroupedDocument[0].VectorSpace[j] = total / _clust[i].GroupedDocument.Count();
}
}
}
return _clust;
}
You may have some side effects in FindCosineSimilarity, make sure it does not modify any field or input parameter. Example: resultSet[ind].GroupedDocument.Add(obj);. If resultSet is not a reference to locally instantiated array, then that is a side effect.
That may fix it. But FYI you could use AsParallel for this rather than Parallel.For:
similarityMeasure = clustercenter
.AsParallel().AsOrdered()
.Select(c=> SimilarityMatrics.FindCosineSimilarity(c.GroupedDocument[0].VectorSpace, obj.VectorSpace))
.ToArray();
You realize that if you synchronize the whole Content of the Parallel-For, it's just the same as having a normal synchrone for-loop, right? Meaning the code as it is doesnt do anything in parallel, so I dont think you'll have any Problems with concurrency. My guess from what I can tell is clustercenter[i].GroupedDocument is propably an empty Array.
I'm trying to create a class wide array in C#, in a Windows Mobile Phone 8.1 project, so that when I create a method I can
What I did at first was:
public sealed partial class GamePage : Page
{
int Score = 0;
int count = 0;
private DispatcherTimer Timer;
public ColorsClass color = new ColorsClass();
public int RandBlue = 0;
int RandGreen = 0;
int RandRed = 0;
int RandYellow = 0;
int RandPurple = 0;
int RandYellowGreen = 0;
int RandOrange = 0;
int RandGray = 0;
bool Equal = true;
int Fail;
int Hit;
int Lives = 10;
Rectangle[] Block = { Block01, Block02, Block03, Block04, Block05, Block06, Block07, Block08, Block09, Block10, Block11, Block12 };
int[] RandomColors = { RandBlue, RandGreen, RandRed, RandYellow, RandPurple, RandYellowGreen, RandGray };
...
}
But it gives me the message that "a field initializer cannot reference the non-static field, method or property..."
Then I tried this option, that I saw when I was search in the internet:
public sealed partial class GamePage : Page
{
int Score = 0;
int count = 0;
private DispatcherTimer Timer;
public ColorsClass color = new ColorsClass();
public int RandBlue = 0;
int RandGreen = 0;
int RandRed = 0;
int RandYellow = 0;
int RandPurple = 0;
int RandYellowGreen = 0;
int RandOrange = 0;
int RandGray = 0;
bool Equal = true;
int Fail;
int Hit;
int Lives = 10;
int []
Random rand = new Random();
public GamePage()
{
this.InitializeComponent();
DispatchTheTime();
RandomColors = new int[] { RandBlue, RandGreen, RandRed, RandYellow, RandPurple, RandYellowGreen, RandGray };
...
}
This way I can reach the array through the methods I created, but the array values are always null..
What can I do?
Everytime when you create a new GamePage you are filling your array with the content of the variables RandGreen, RandRed, ...
At this time, these variables are set to 0. Thus your array contains only 0s. Even if you later assign other values to RandGreen, RandRed, ... the values within the array will not change.
I hope this example will make it clearer:
RandBlue = 0;
var RandomColors = new int[] { RandBlue, RandGreen };
// RandColors[0] is 0
RandBlue = 5;
// RandColors[0] is still 0
Edit:
The error message "a field initializer cannot reference the non-static field, method or property..." should be self-explaining. You could make your color variables const in order to make it work. But I suppose this would not make any sense for you.
Keep in mind that integers are valuetypes. If you create an array of integers like with the RandomColors, you'll just put a copy of your value in the array. At this point, RandGreen and RandomColors[1] point to different memory locations and a change of either won't propagate to the other.
You have to decide whether you want to keep your values in a lot of fields like you actually declared or if you want to keep your integers in an array.
You are propably better off using a Dictionary for your usecase and only access the integers from there.
On class level declare your RandomColors:
Dictionary<string, int> RandomColors = new Dictionary<string, int>();
public GamePage()
{
RandomColors.Add("RandGreen", 0);
RandomColors.Add("RandRed", 0);
//change like this:
RandomColors["RandGreen"] = 5;
//access like this:
int x = RandomColors["RandGreen"];
}
As the title suggests I am initializing objects in a list through a loop. But they all become identical when the loop exits. I can see during the loop that they are not the same. but when the loop exits they change to the last object entered.
public List<ElevationLayout> layoutList = new List<ElevationLayout>();
public int layoutNumber { get; set; }
public int worldWidth { get; set; }
public Random seed { get; set; }
public XYSize dimLeft { get; set; }
//I have narrowed down the problem to this method
//==========================================================================================================================================================
//==========================================================================================================================================================
//==========================================================================================================================================================
public void init(World world) {
dimLeft = new XYSize();
ElevationLayout layout = new ElevationLayout();
dimLeft.y = 0;
dimLeft.x = world.size.x;
seed = new Random((int)DateTime.Now.Ticks);
worldWidth = (int)((world.size.x / 6.4) + (world.size.x / 64) - 1);
layoutNumber = worldWidth + seed.Next(-2, 3);
for (int i = 0; i < layoutNumber; i++)
{
layout.type = seed.Next(0, 2);
layout.width = (world.size.x / layoutNumber) + seed.Next(0, ((dimLeft.x / layoutNumber) / 2) + 1);
if (layout.width > dimLeft.x)
{
layout.width = dimLeft.x;
}
dimLeft.x -= layout.width;
layout.height = seed.Next(world.size.y / 16, (world.size.y / 4) + 1);
if (layout.height > dimLeft.y)
{
layout.height = dimLeft.y;
}
this.layoutList.Add(layout);
Console.Write(this.layoutList[i].type); // here the objects are different
if ((world.size.y -= layout.height) > dimLeft.y)
{
dimLeft.y = (world.size.y - layout.height);
}
if (dimLeft.x <= 0)
{
layoutNumber = i;
}
}
Console.WriteLine();
for (int y = 0; y < layoutNumber; y++)
Console.Write(this.layoutList[y].type); //but as soon as i exit the loop they are the same
}
//==============================================================================================================
//==============================================================================================================
//==============================================================================================================
Someone had a similar problem here: Why is my list of objects all the same?
and here: Why are all the values in my list the same?
Initially my list of objects was static, but i have since removed that and the problem remains.
The problem is that you only create one instance of the object before the loop and set the properties of that one object.
Fix:
for (int i = 0; i < layoutNumber; i++)
{
ElevationLayout layout = new ElevationLayout();
Basically create your object inside the loop, so that on every iteration you allocate a new object.
You're adding the same layout to the list over and over, rather than creating a new instance of layout each time. Move the code to create the layout object inside the loop.