delete integer from NSArray - nsmutablearray

I have to delete an instance from an array, but when I delete the instance all instances with the same value are deleted. The code I use works great with other objects, like Sprites, but not with integers.
Who can point me in the right direction?
The value of deleteSpriteNr is de object to delete, i have also used [levelSpriteNrArray removeObjectAtIndex:deleteSpriteNr] at the end of the for loop, but that generates a crash.
i am puzzled.
The code:
int tel3 = 0;
for (NSNumber *spriteNr in levelSpriteNrArray ){
if ( tel3 == deleteSpriteNr ){
[spriteNrToRemove addObject:spriteNr];
//[spriteNr removeFromParentAndCleanup:YES] // does not works with integer;
}
tel3++;
}
[levelSpriteNrArray removeObjectsInArray:spriteNrToRemove];

Try to do so. Hope this will help.
int tel3 = 0;
NSMutableIndexSet *indexes = [NSMutableIndexSet new];
for (int i = 0; i < [levelSpriteNrArray count]; i++ ){
if ( tel3 == deleteSpriteNr ){
[indexes addIndex:i];
//[spriteNr removeFromParentAndCleanup:YES] // does not works with integer;
}
tel3++;
}
[levelSpriteNrArray removeObjectsAtIndexes:indexes];

Related

Will it be simpler to convert this code from CStringArray to std::vector<CString>?

Given this code:
void CSelectNamesDlg::ShuffleArray(CString strName, CStringArray *pAryStrNames)
{
if (pAryStrNames == nullptr)
return;
const auto iSize = pAryStrNames->GetSize();
if (iSize > 1)
{
// First, we must locate strName in the array
auto i = CSelectNamesDlg::LocateText(strName, pAryStrNames);
if (i != -1)
{
const auto iName = i;
// We must now shuffle the names from the bottom to the top
const auto iCount = gsl::narrow<int>(iSize) - iName;
for (i = 0; i < iCount; i++)
{
CString strTemp = pAryStrNames->GetAt(iSize-1);
pAryStrNames->RemoveAt(iSize-1);
pAryStrNames->InsertAt(0, strTemp);
}
}
}
}
int CSelectNamesDlg::LocateText(CString strText, const CStringArray *pAryStrText)
{
bool bFound = false;
int i{};
if (pAryStrText != nullptr)
{
const auto iSize = pAryStrText->GetSize();
for (i = 0; i < iSize; i++)
{
if (pAryStrText->GetAt(i) == strText)
{
// Found him!
bFound = true;
break;
}
}
}
if (!bFound)
i = -1;
return (int)i;
}
If I convert my CStringArray into a std::vector<CString is it going to be simpler to achieve the same PerformShuffle and LocateText methods?
Should I just stay with CStringArray?
I know of 1 (ONE!) benefit of MFC array over std::vector - they support MFC-style serialization. If you use it - you may be stuck.
However, if you don't - I would use std::vector<CString>. Your LocateText (that is overly verbose) will become obsolete - just use find
Also, your ShuffleArray is very inefficient (remove/insert one item at a time). Using a vector will allow you to do something like Best way to extract a subvector from a vector?

Why is the rcpp function slow?

I have made a simple function that sets a column reversal_indicator to "yes" if a value in the Reversal_Accounting_Transaction_ID is present anywhere in the column Accounting_Transaction_ID (i.e in other rows).Most entries in the Reversal_Accounting_Transaction_ID column are likely to be blank and therefore should be "no".
The dataframe is created from a 6gb csv file (assume approx 6 million rows) and is being processed on databricks.
I am not really sure why its taking such a long time
Rcpp::cppFunction('
std::vector<std::string>
reversals(DataFrame frame)
{
std::vector<std::string> Accounting_Transaction_ID = as<std::vector<std::string> >(frame["BELNR"]);
std::vector<std::string> Reversal_Accounting_Transaction_ID = as<std::vector<std::string> >(frame["STBLG"]);
std::vector<std::string> ReversalIndicator(Reversal_Accounting_Transaction_ID.size()) ;
if (Reversal_Accounting_Transaction_ID.size() == 0) {
return ReversalIndicator;
}
int dfSize = Reversal_Accounting_Transaction_ID.size();
for (int i = 0; i < dfSize; ++i) {
if (Reversal_Accounting_Transaction_ID[i] != "") {
for (int j = 1; j < dfSize; ++j) {
if(Accounting_Transaction_ID[j]== Reversal_Accounting_Transaction_ID[i]){
ReversalIndicator[i]="Yes";
break;
}
else if( (j== dfSize -1) ){
ReversalIndicator[i]="No";
}
}
}
else{
ReversalIndicator[i]="No";
}
}
return ReversalIndicator;
}
')```
```df$reversal=reversals(df)```
You are traversing your data frame for every row of your data frame, i.e. you have something like 6m x 6m operations (O(N^2)). That can take quite a while. However, you can go from O(N^2) to O(N) at the expense of some memory. Without any sample data I cannot test this, so I am providing some pseudo code only:
create empty set data structure
for each row in df:
Add Reversal_Accounting_Transaction_ID to set
for each row in df:
if Accounting_Transaction_ID can be found in set
ReversalIndicator = "Yes"
Based on Ralphs answer
Not sure if I need to allocate the set a size at the start though?
Rcpp::cppFunction('
std::vector<std::string> reversals(DataFrame frame)
{
std::vector<std::string> Accounting_Transaction_ID = as<std::vector<std::string> >(frame["BELNR"]);
std::vector<std::string> Reversal_Accounting_Transaction_ID = as<std::vector<std::string> >(frame["STBLG"]);
std::vector<std::string> ReversalIndicator(Reversal_Accounting_Transaction_ID.size()) ;
std::set<std::string> uniqueTransID;
if (Reversal_Accounting_Transaction_ID.size() == 0) {
return ReversalIndicator;
}
int dfSize = Reversal_Accounting_Transaction_ID.size();
for (int i = 0; i < dfSize; ++i) {
uniqueTransID.insert(Accounting_Transaction_ID[i]);
}
for (int i = 0; i < dfSize; ++i) {
if (Reversal_Accounting_Transaction_ID[i] !=""){
ReversalIndicator[i]="No";
continue;
}
if (uniqueTransID.find(Reversal_Accounting_Transaction_ID[i]) != uniqueTransID.end()) {
ReversalIndicator[i]="Yes";
}
else{
ReversalIndicator[i]="No";
}
}
return ReversalIndicator;
}
')```

How can i download only new records from Anviz EP300?

All,
Currently i'm using Anviz EP300 time attendance machine. I need to download only new records from device.
I'm using following sdk. Click here
There is some method already have in sdk. Which is i used like...
int i = 0;
int Ret = 0;
int RecordCount = 0;
int RetCount = 0;
int pClockings = 0;
int pLongRun = 0;
CKT_DLL.CLOCKINGRECORD clocking = new CKT_DLL.CLOCKINGRECORD();
clocking.Time = new byte[20];
int ptemp = 0;
ProgressBar1.Value = 0;
//If CKT_GetClockingNewRecordEx(IDNumber, pLongRun) Then 'IF GET NewRecord
if (CKT_DLL.CKT_GetClockingNewRecordEx(IDNumber, ref pLongRun) != 0) //IF GET Record
{
while (true)
{
Ret = CKT_DLL.CKT_GetClockingRecordProgress(pLongRun, ref RecordCount, ref RetCount, ref pClockings);
if (RecordCount > 0)
{
ProgressBar1.Maximum = RecordCount;
}
if (Ret == 0)
{
return;
}
if (Ret != 0)
{
ptemp = pClockings;
for (i = 1; i <= RetCount; i++)
{
PCopyMemory(ref clocking, pClockings, CKT_DLL.CLOCKINGRECORDSIZE);
pClockings = pClockings + CKT_DLL.CLOCKINGRECORDSIZE;
insertTimeAttendance(clocking.PersonID, clocking.Stat, Encoding.Default.GetString(clocking.Time), clocking.ID);
ProgressBar1.Value += 1;
}
if (ptemp != 0)
{
CKT_DLL.CKT_FreeMemory(ptemp);
}
}
if (Ret == 1)
{
return;
}
}
}
CKT_GetClockingNewRecordEx that method should be return new records. But it returns all records.
I guess, there is should be one method or config should be mark as downloaded.
Anyone some idea or solution?
Thanks,
Eba
I created the SDK you downloaded (basically written in Vb, and I just convert it to C#)
Actually for the Anviz EP300 device, there is no way you can just retrieve new records,neither retrieve user lists (for example), at list with that SDK.. It has a lot of methods, but unfortunately few of them works fine. You will have to Use CKT_GetClockingRecordEx, instead of CKT_DLL.CKT_GetClockingNewRecordEx

Windows phone:Do not allow more than one dot in a textbox?

I am writing application in windows phone 8.
I need to provide a textbox which will allow user to enter only "Numbers" and if required, only one dot ".
I set <TextBox InputScope="Number" /> but it allow multiple dot.
How can i set single dot in textbox of windows phone?
Set an event that triggers everytime a text has change like this:
<TextBox x:Name="textBox1" TextChanged="textBox1_TextChanged" />
And then in the event function loop through the text, count the dots and if the dot count is higher than 1, delete the said dot.
EDIT: you said if I could provide a sample algorithm:
string str = textBox1.Text;
int dotCount = 0;
for (int i = 0; i < str.Length; i++)
{
if (str[i] == '.')
{
dotCount++;
if (dotCount > 1)
{
str.Remove(i, 1);
i--;
dotCount--;
}
}
}
This code is not working as it should so I made some improvements.. hope it helps! I'm using KeyUp but TextChange is also OK to use.
private void tbMainText_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
TextBox tb = (TextBox)sender; //Getting the textbox which fired the event if you assigned many textboxes to the same event.
string str = tb.Text;
int dotCount = 0;
for (int i = 0; i < str.Length; i++)
{
if (str[i] == '.')
{
dotCount++;
if (dotCount > 1)
{
str = str.Remove(i, 1); //Assigning the new value.
i--;
dotCount--;
}
}
}
tb.Text = str;
tb.Select(tb.Text.Length, 0); //Positioning the cursor at end of textbox.
}

Problem with SafeArray access using CComVariant

I have following block of code
/////////////////////////////////////
CComVariant newVal;
//pass the CComVariant and get the strings array!!!
GetStrList(newVal);
USES_CONVERSION;
if (((newVal.vt & VT_ARRAY) == VT_ARRAY) && ((newVal.vt & VT_BSTR) == VT_BSTR))
{
SAFEARRAY* paArray = newVal.parray;
BSTR * str = NULL;
SafeArrayAccessData(paArray, (void**)&str);
SafeArrayUnaccessData(paArray);
long lLBound = 0;
long lUBound = 0;
long nCount = 0;
if (FAILED(SafeArrayGetLBound(paArray, 1, &lLBound)) ||
FAILED(SafeArrayGetUBound(paArray, 1, &lUBound)))
{
ASSERT(false);
return FALSE;
}
nCount = ( lUBound - lLBound + 1 );
for (int i = 0 ; i < nCount ; i++)
{
m_cstrList.AddString(W2T(str[i]));
}
//SafeArrayDestroy(paArray); ---> is it required here???
}
/////////////////////////////////////
method returing the safe arrays
HRESULT GetStrList(VARIANT *pVal)
{
USES_CONVERSION;
if (!pVal)
return E_FAIL;
SAFEARRAYBOUND bound[1]; //single dimension array
bound[0].lLbound = 0;
bound[0].cElements = 10;
SAFEARRAY * A = SafeArrayCreate(VT_BSTR, 1, bound);
BSTR * str = NULL;
SafeArrayAccessData(A, (void**)&str);
//user wants the NT view OPC drivers list.
for (int i=0;i<10;i++)
{
str[i] = SysAllocString(T2W(mystrings[i]));
}
VariantInit(pVal);
pVal->vt = VT_ARRAY | VT_BSTR;
pVal->parray = A;
SafeArrayUnaccessData(A);
A = NULL;
return S_OK;
}
My doubt is, above first block of code has any memory leaks?
Does the CComVariant itself handle every thing about the cleaning?
or do i also manually do SafeArrayDestroy(paArray);
Thanks in Advance!
CComVariant destructor calls VariantClear() which frees whatever the variant was incapsulating, arrays included.
One caveat: the array should not be locked at the time when VariantClear() is called. This means that if an exception is thrown after SafeArrayAccessData() but before SafeArrayUnaccessData() the latter will not be called and VariantClear() will not free resources.
Therefore you better write a bracket class for pairing SafeArrayAccessData() and SafeArrayUnaccessData() calls.

Resources