Can't remove list element defined inside class? - list

I can't seem to remove an element from a List defined inside a class:
class something {
List<int> numbers = [
70,
80,
90,
];
void PrintElementTwVo() {
print(numbers[2]);
}
void RemoveElement() {
PrintElementTwo(); // prints 80
numbers.remove(2); // should remove 80
PrintElementTwo(); // still prints 80 even after it got removed?
}
}
Someone knows what is going on here?

Have you read the help for remove method? You should use removeAt method instead.

Related

Unity / C#: using lists to store numbers, delete elements

I have been banging my head on a problem related to lists. I am a beginner, so sorry if this is a bit unclear..
My goal is to be able to write numbers from keyboard inputs, that will be displayed in a UI element in Unity.
To do so i decided to use a list, because i was wanting to add control to the display, (for example, to add a "." every 3 digits so that they would be more easily readable, like "3.489.498").
So basically, i store new inputs in this list, then i display this list with a display.text every time there is a new digit as an input.
This works actually very well, but then i wanted to be able to delete the last typed element. So i added a backspace hotkey with a List.Remove().
And this is where the nightmare starts. The thing seems to work when i press "1" and deletes right after, but for some reasons it does not work with 2.
Error message is : "Argument out of range, parameter name: index."
I just can't wrap my head around this problem :(
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class BoxCreateNumber : MonoBehaviour {
public Text textDisplayNumber;
public List<int> numberList = new List<int>();
void Start () {
}
void Update () {
CollectingNumberInput ();
}
void CollectingNumberInput(){
if (Input.GetKeyDown(KeyCode.Keypad1)){
numberList.Add (1);
//numberList.Insert (numberList.Count,1);
DisplayNumber ();
} else if (Input.GetKeyDown(KeyCode.Keypad2)) {
numberList.Add (2);
//numberList.Insert (numberList.Count,2);
DisplayNumber ();
} else if (Input.GetKeyDown(KeyCode.Backspace)) {
numberList.Remove(numberList.Count);
DisplayNumber ();
}
}
void DisplayNumber(){
textDisplayNumber.text = "";
for (int i = 0; i <= numberList.Count; i++) {
textDisplayNumber.text += numberList [i];
}
}
}
You just need to read the documentation.
public bool Remove(
T item
)
Parameters
item - The object to remove from the List. The value can be null for reference types.
Instead of passing the function the object to remove, you pass the number of elements in the list. This means that if the list contains element "1" as its only element, then it will work, but only by accident.
Calling RemoveAt(numberList.Count - 1) will do what you want. RemoveAt takes the index of the element to remove, and the indices are 0-based, so the last one is Count-1.
Try this to remove the last element
numberList.RemoveAt(numberList.Count-1);

Opposite of 'is' in if statement?

I want to see if this statement is false:
if twData is Array {
}
isnt and isnot don't seem to exist.
This doesn't work:
if (twData is Array) == false {
}
So I'm not sure exactly how to do this, other than the less clean:
if twData is Array {
} else {
//Code goes here
}
If you know the generic type stored in the array, then you should make it explicit:
if !(twData is Array<Int>) {
// Do something
}
If instead you just want to know if it's an array regardless of the generic type, then you have to use NSArray:
if !(twData is NSArray) {
}
Documentation says:
let isarray = twData is Array
if !isarray {
do something
}

C++ Function will not execute more than once

I've tried looking around but I can't find anything about this anywhere.
I'm writing a custom array class with a "push" function to add a value to the array.
It seems to work perfectly fine but won't execute more than once.
Take the main method below for example:
int main()
{
Array<int> test(4,5);
test.push(4);
test.writeOrdered("Output.txt");
return 0;
}
This will put the int value 4 into the array at the first available position and execute the writeOrdered function.
The following main method, on the other hand:
int main()
{
Array<int> test(4,5);
test.push(4);
test.push(5);
test.writeOrdered("Output.txt");
return 0;
}
This will put the number 4 into the array at the first available point as above and then stop. It won't execute any further lines of code.
Here's the push function for reference:
void push(Datatype p_item)
{
bool inserted = false;
int i = 0;
while (inserted == false)
{
if (m_array[i] < 0)
{
m_array[i] = p_item;
i++;
inserted = true;
cout << p_item << " saved to array" << endl;
system("pause");
}
}
}
You have an infinite loop. After the first insert m_array[0] >= 0 and i never grows. You would have found it out, had you debugged the code somehow.
Basically I don't understand your push function but the way it is, after you insert a non-negative value into the first position any further call to your push function results in a tight loop.
I imagine that you want the i++ outside the if statement.
Without seeing the full implementation of the Array class I would guess that the array m_array contains negative numbers by default. This will allow the first call to the push method to succeed. The next call to the method contains a value of 4 at index 0 and will be stuck in an infinite loop because inserted will never be set to true nor will the value of i be incremented.

C++ Static array

I would like to create a custom lower / upper case function for wstrings.
Therefore I am using a map of integers.
Currently I am automatically creating a function from these maps:
(...)
else if (iCharCode==65)
{
iRet=97;
}
else if (iCharCode==66)
{
iRet=98;
}
else if (iCharCode==67)
{
iRet=99;
}
else if (iCharCode==68)
{
iRet=100;
}
else if (iCharCode==69)
{
iRet=101;
}
else if (iCharCode==70)
{
iRet=102;
}
else if (iCharCode==42818)
{
iRet=42819;
}
(...)
However, the function is going to be pretty large if I turn my map into a if-statement like this.
I would therefore like a use a real map instead, but I don't want to load it at runtime.
I would prefer having a static map, but I am not sure how to do that.
Can somebody share his thoughts?
Maybe the following code can help:
#include<iostream>
#include<map>
std::map<int, int> code_map = {
{65, 97},
{66, 98},
{67, 99},
{68, 100},
{69, 101},
{70, 102},
};
int main() {
for(const auto & pair : code_map) {
std::cout<<pair.first<<" maps to "<<pair.second<<std::endl;
}
return 0;
}
Compiling with g++ example.cpp -std=c++11 -Wall -Wextra (OS X 10.7.4 GCC 4.8.1) yields:
$ ./a.out
65 maps to 97
66 maps to 98
67 maps to 99
68 maps to 100
69 maps to 101
70 maps to 102
You could implement the map as a sorted array of pairs. This can be initialised statically. Look up a value using a binary search, e.g. std::lower_bound with a comparator comparing the first element of each pair.
As further optimisation, you might consider mapping ranges rather than individual characters, using an array of (range_begin, range_end, offset) triplets. This would reduce the whole ASCII alphabet to a single entry; but might be less effective for other alphabets.

Unable to access contents of initialized struct from a vector

I have a struct:
typedef struct
{
Qt::Key qKey;
QString strFormType;
} KeyPair;
Now I initialize KeyPair instantiations so I could use it for my Automated Test App.
KeyPair gTestMenu[] =
{
{ Qt::Key_1 , "MyForm" },
{ Qt::Key_1 , "SubForm" },
{ Qt::Key_Escape, "DesktopForm" }
};
KeyPair gBrowseMenu[] =
{
{ Qt::Key_1 , "MyForm" },
{ Qt::Key_2 , "Dialog" },
{ Qt::Key_Escape, "DesktopForm" }
};
and like 100 more instantiations....
Currently, I call a function which uses these KeyPairs.
pressKeyPairs( gTestMenu );
pressKeyPairs( gBrowseMenu );
and more calls for the rest...
I would like to put all these KeyPair instantiations in a vector so I wouldn't have to call pressKeyPairs() a hundred times... I'm a newbie in using vectors... so I tried:
std::vector<KeyPair, std::allocator<KeyPair> > vMasterList;
vMasterList.push_back( *gTestMenu );
vMasterList.push_back( *gBrowseMenu );
std::vector<KeyPair, std::allocator<KeyPair> >::iterator iKeys;
for(iKeys = vMasterList.begin(); iKeys != vMasterList.end(); ++iKeys)
{
pressKeyPairs(*iKeys);
}
However, this code block isn't working... :( Can somebody tell me how to properly put these KeyPairs in a vector?
You've to use insert to populate the vector with your different arrays. Here is how you should do it.
//initialized with one array
std::vector<KeyPair> vMasterList(gTestMenu, gTestMenu + 3);
//adding more items
vMasterList.insert( vMasterList.end(), gBrowseMenu , gBrowseMenu + 3);
And then reimplement your pressKeyPair function, so that you can use std::for_each from <algorithm> header file as,
//pressKeyPair will be called for each item in the list!
std::for_each(vMasterList.begin(), vMasterList.end(), pressKeyPair);
Here is how you can write the pressKeyPair function:
void pressKeyPair(KeyPair &keyPair) //takes just one item!
{
//press key pair!
}
In my opinion, this is better design, as it doesn't need "manual" loop anymore at the calling site!
You can even call pressKeyPair for first 5 items in the list as,
//pressKeyPair will be called for first 5 items in the list!
std::for_each(vMasterList.begin(), vMasterList.begin() + 5, pressKeyPair);
One more example:
//pressKeyPair will be called for 5 items after the first 5 items, in the list!
std::for_each(vMasterList.begin()+5, vMasterList.begin() + 10, pressKeyPair);
EDIT:
If you want to use manual loop, then you've to use this:
std::vector<KeyPair>::iterator it;
for( it = vMasterList.begin(); it != vMasterList.end(); ++it)
{
pressKeyPair(*it);
}
But I would say it's not as elegant as the approach described earlier. Remember, this assumes that the function pressKeyPair has this signature:
void pressKeyPair(KeyPair &keyPair); //it doesn't accept array!
I think that the problem is that the code
vMasterList.push_back( *gTestMenu );
Only adds a single element of gTestMenu to the vector, namely the first. The reason is that this code is equivalent to the following:
vMasterList.push_back( gTestMenu[0] );
From which I think it's a bit easier to see what's going wrong.
To fix this, you probably want to add all of the elements in gTestMenu to the master list. You can do this using the three-parameter vector::insert function:
vMasterList.insert(v.begin(), // Insert at the beginning
gTestMenu, // From the start of gTestMenu...
gTestMenu + kNumTests); // ... to the end of the list
Here, you'll need to specify how many tests are in gTestMenu as kNumTests. You can do the same for gBrowseMenu.
By the way, you don't need to specify the allocator type in the vector declaration if you just want to use the default std::allocator. You can just write
std::vector<KeyPair> vMasterList;
And you'll be totally fine.