Suddenly problem with lambda in foreach statement:
IEnumerator RefreshNextFrame( Part Current )
{
yield return null;
if( Current.Nodes == null )
yield break;
Current.Nodes.ForEach( n => Debug.Log( n.name ) );//outputs node0, node1
for( int i = 0; i < Current.Nodes.Count; i++ )
{
Node node = Current.Nodes[i];
Button button = Instantiate( Resources.Load<GameObject>( "Prefabs/Button" ) ).GetComponent<Button>();
button.transform.SetParent( content );
button.GetComponentInChildren<Text>().text = node.name;
button.onClick.AddListener( delegate
{
Debug.Log( button.GetComponentInChildren<Text>().text );
} );
}
}
Clicking on buttons always output node1
Just assign to a new local variable on each iteration and use that local variable for the AddListener.
EDIT
Quick example:
MyFunction will always receive 100 as the value of i on this:
for (int i=0; i<100; i++) {
button.onClick.AddListener(() => MyFunction(i));
}
But if you do this it will work correctly:
for (int i=0; i<100; i++) {
int iLocal = i;
button.onClick.AddListener(() => MyFunction(iLocal));
}
Everything because of this code is in couroutine. Here is the answer http://answers.unity3d.com/answers/974195/view.html
Related
I want skip my in foreach. For example:
foreach(Times t in timeList)
{
if(t.Time == 20)
{
timeList.Skip(3);
}
}
I want "jump" 3 positions in my list.. If, in my if block t.Id = 10 after skip I want get t.Id = 13
How about this? If you use a for loop then you can just step the index forward as needed:
for (var x = 0; x < timeList.Length; x++)
{
if (timeList[x].Time == 20)
{
// option 1
x += 2; // 'x++' in the for loop will +1,
// we are adding +2 more to make it 3?
// option 2
// x += 3; // just add 3!
}
}
You can't modify an enumerable in-flight, as it were, like you could the index of a for loop; you must account for it up front. Fortunately there are several way to do this.
Here's one:
foreach(Times t in timeList.Where(t => t.Time < 20 || t.Time > 22))
{
}
There's also the .Skip() option, but to use it you must break the list into two separate enumerables and then rejoin them:
var times1 = timeList.TakeWhile(t => t.Time != 20);
var times2 = timeList.SkipeWhile(t => t.Time != 20).Skip(3);
foreach(var t in times1.Concat(times2))
{
}
But that's not exactly efficient, as it requires iterating over the first part of the sequence twice (and won't work at all for Read Once -style sequences). To fix this, you can make a custom enumerator:
public static IEnumerable<T> SkipAt<T>(this IEnumerable<T> items, Predicate<T> SkipTrigger, int SkipCount)
{
bool triggered = false;
int SkipsRemaining = 0;
var e = items.GetEnumerator();
while (e.MoveNext())
{
if (!triggered && SkipTrigger(e.Current))
{
triggered = true;
SkipsRemaining = SkipCount;
}
if (triggered)
{
SkipsRemaining--;
if (SkipsRemaining == 0) triggered = false;
}
else
{
yield return e.Current;
}
}
}
Then you could use it like this:
foreach(Times t in timeList.SkipAt(t => t.Times == 20, 3))
{
}
But again: you still need to decide about this up front, rather than inside the loop body.
For fun, I felt like adding an overload that uses another predicate to tell the enumerator when to resume:
public static IEnumerable<T> SkipAt<T>(this IEnumerable<T> items, Predicate<T> SkipTrigger, Predicate<T> ResumeTrigger)
{
bool triggered = false;
var e = items.GetEnumerator();
while (e.MoveNext())
{
if (!triggered && SkipTrigger(e.Current))
{
triggered = true;
}
if (triggered)
{
if (ResumeTrigger(e.Current)) triggered = false;
}
else
{
yield return e.Current;
}
}
}
You can use continue with some simple variables.
int skipCount = 0;
bool skip = false;
foreach (var x in myList)
{
if (skipCount == 3)
{
skip = false;
skipCount = 0;
}
if (x.time == 20)
{
skip = true;
skipCount = 0;
}
if (skip)
{
skipCount++;
continue;
}
// here you do whatever you don't want to skip
}
Or if you can use a for-loop, increase the index like this:
for (int i = 0; i < times.Count)
{
if (times[i].time == 20)
{
i += 2; // 2 + 1 loop increment
continue;
}
// here you do whatever you don't want to skip
}
I have a queue[i] for each drone[i].
MY QUESTION: How can make a code that waits for each drone[i].actual_position == drone[i].desired_position instead of my current code that only waits if the current drone drone[i]desired_position == drone[i].actual_position
So instead of this:
for (int i = 0; i < drones.Length; i++)
{
queue[i].Enqueue(drone[i].desired_position);
if (drone[i]desired_position == drone[i].actual_position)
{
queue[i].Dequeue();
queue[i].Enqueue(next_desired_position);
}
}
I want something like this:
for (int i = 0; i < drones.Length; i++)
{
queue[i].Enqueue(drone[i].desired_position);
//TODO: what should I put into "if"?
if (/* all drone[i]desired_position == drone[i].actual_position */)
{
queue[i].Dequeue();
queue[i].Enqueue(next_desired_position)
}
}
TLDR: I want to make sure every drone is in his desired position before dequeue and go to the next position so the drones are syncronized.
It seems that you're looking for an All Linq command as well as for loop and if swapped:
// If all drones are at their expected positions
if (drone.All(d => d.desired_position == d.actual_position))
// then set new goals for each drone:
for (int i = 0; i < drone.Length; ++i) {
// remove the target achieved
queue[i].Dequeue();
// but add a new location to go
queue[i].Enqueue(next_desired_position)
}
I guess what you´re lookging for is Linq´s All-method:
var allOkay = drones.All(d => d.desired_position == d.actual_position);
if(allOkay)
{
foreach(var drone in drones)
drone.Dequeue();
}
I have a Form that contains a Menu with two entries, which are Menu and Tools. The two Menues have some SubMenus.
Now i have a TextBox called txtSelect and a Button called btnVisible, if I enter 1,2 in the TextBox, the SubMenus in the Menu should not be visible. I written the following code, bit it is Hard-written.
ToolStripMenuItem[] mstrip = new ToolStripMenuItem[] { msO1, msO2, msO3, msP1, msP2, msP3 };
if (txtSelect.Text.Length > 2)
{
string word = txtSelect.Text;
string[] splt = word.Split(',');
for (int x = 0; x < mstrip.Length; x++)
mstrip[x].Visible = true;
for (int x = 0; x < splt.Length; x++)
{
int y = Convert.ToInt32(splt[x].ToString()) - 1;
if (y >= 0 && y < mstrip.Length)
mstrip[y].Visible = false;
textBox1.AppendText(mstrip[y].Text);
textBox2.AppendText(mstrip[y].OwnerItem.Text);
}
}
I want to use foreach loop instead in a Button Click Event and have attempted with the following, however the result is not the same as with the code above.
foreach (ToolStripMenuItem mnItem in msMenus.Items)
{
MessageBox.Show(mnItem.Text);
for (int i = 0; i < mnItem.DropDown.Items.Count; i++)
{
MessageBox.Show(mnItem.DropDown.Items[i].Text);
mnItem.DropDown.Items[i].Visible = true;
}
}
Well, may be you want something like :
List<Int32> lstindex = new List<Int32>();
String[] splt = txtSelect.Text.Split(',');
// initialize list of indexed for textbox
foreach (String str in splt)
{
lstindex.Add(Convert.ToInt32(str) - 1);
}
// for each menu
foreach (ToolStripMenuItem mnItem in msMenus.Items)
{
// for each menu item
foreach (ToolStripItem item in mnItem.DropDown.Items)
{
// if index of item is in the list of indexed, set visible to false, otherwise to true
item.Visible = lstindex.Contains(mnItem.DropDown.Items.IndexOf(item)) ? false : true;
}
}
I have a list of Buttons and I want to get the two elements that are 'equal':
for (int i = 0; i < Memory.Count; i++ )
{
piezas = Memory.FindAll(s => (s.Name != Memory[i].Name && Utilidades.CompareImage(s.Image, Memory[i].Image)));
}
This is supposed (if I'm not wrong) the list with the two elements that have different Name but are using the same Image. I'm more than sure that such elements exists... but I don't know why this doesn't work.
"Utilidades.CompareImage" is an static method:
public static bool CompareImage(Image firstImage, Image secondImage)
{
MemoryStream ms = new MemoryStream();
firstImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
String firstBitmap = Convert.ToBase64String(ms.ToArray());
ms.Position = 0;
secondImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
String secondBitmap = Convert.ToBase64String(ms.ToArray());
if (firstBitmap.Equals(secondBitmap))
return true;
else
return false;
}
I've tested the method before and it's working as intented.
Can you please help me?
The code
for (int i = 0; i < Memory.Count; i++ )
{
var piezas = Memory.FindAll(s => (s.Name != Memory[i].Name
&& Utilidades.CompareImage(s.Image, Memory[i].Image)));
}
creates a new 'piezas' every time and then doesn't use it.
Also you are checking all combinations twice.
So do you want to find all pairs, the first pair or maybe something in between?
A quick fix, but far from perfect,
for (int i = 0; i < Memory.Count; i++ )
{
var piezas = Memory.FindAll(s => (s.Name != Memory[i].Name
&& Utilidades.CompareImage(s.Image, Memory[i].Image)));
if (piezas.Count > 0)
{
// use piezas[0] somehow
break;
}
}
It seems no one mentioned SelectMany yet:
var pieza = Memory.SelectMany((m, i) =>
Memory.Where((m2, j) => i < j && m.Name != m2.Name &&
Utilidades.CompareImage(m.Image, m2.Image))
.Select(m2 => Tuple.Create(m, m2))).First();
if you want all pairs, not just one, replace the final First() call to ToList() or something like that.
I have
public string[] ButtonList()
{
string[] buttons = { "A", "B", "Back", "BigButton", "etc..." }
return buttons;
}
private void EchoButtons()
{
for (int i = 0; i < ButtonList().Length; i++)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.A == ButtonState.Pressed)
{
// Echo the buttons
}
}
}
Is there anyway i could use the string from the array to define the button?
Example (although this does't work):
for (int i = 0; i < ButtonList().Length; i++)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.ButtonList()[i] == ButtonState.Pressed)
{
// Echo the buttons
}
}
Edit: i hope this makes sense, i wasn't sure i explained it well.
You can use a list of delegates which have GamePadState as a parameter, and return the state for the desired buttons.
var getButtonState = new List<Func<GamePadState, ButtonState>>
{
s => s.Buttons.A,
s => s.Buttons.B,
...
};
// Example to get the state of the first item in the list.
ButtonState state = getButtonState[0]( GamePad.GetState( PlayerIndex.One ) );