How to remove a specific element from an array in Crystal Lang? - crystal-lang

I have an array of multiple types ( Int32 | Char | String ) and need to remove a specific element.
Is there a simple way to do that?

You may use Array(T).delete_at(index) to delete an element at a given index in your array, or Array(T).delete(obj) that deletes all elements in the array that are equal to obj

Inspired by Shree's now deleted answer
new_arr = arr.reject{ |element| element == "whatever"} or could use reject!

Related

Reversing Array Without Using Array Size

It is relatively easy to reverse an array given a pointer to the array and the size of the array.
But my question is: Is it possible to reverse the array given just a pointer to the array?
( in C++ btw)
EDIT
This was a question apparently asked in an interview at Lockheed Martin. See here
In general the answer is NO.
It is only possible for so called terminated arrays like NULL-terminated char array:
void reverse(char* str)
{
int end = -1;
int front = -1;
while (str[++end] != NULL);
while (--end > ++front)
{
char temp = str[end];
str[end] = str[front];
str[front] = temp;
}
}
No it is not possible. If you dont know the size of your array then you cant reverse it.
It can be possible if you define a "terminator" for your array element type, like \0 used for char arrays. You should always end the array with that value, otherwise you'll obtain runtime errors. But it's always better to use the size or avoid arrays and use vectors since you're using c++ and not c.
Nope. Without knowing the size, you cannot use the iterators to reverse it and without using iterators and not knowing the size, it wouldnt be possible to reverse that particular array. You would have to declare another array, copy the contents from the first array into the new array, and perform the content reverse on the new array.

How can i find a particular index in a heap in c++?

I have a vector array a = {1,12,12,6,5}. If i create a max heap than it will return me 12 as a first element. How do i know that the returned 12 is the 2nd or 3rd element of array a? I need the index of the returned element. Thanks.
Create a std::pair<int, int> array, where first element is an actual value and second is an index in initial array. Then, create a heap on this array and get the element index of the top element with maxHeapElement.second.
But remember, that it will always show you the right-most element of the same value since std::pair is compared lexicographical.

How to make sure that recently created area points to NULL?

How can I make sure that, for each allocated new space on heap area, the recently created element of vector of pointers points to NULL ?
Ex:
vector < Sometype* >
vector ----------------------
| | | | ... |
----------------------
new element is pushed back but no available area so double space
index x x+1 y
vector -------------------------------------------
| | | | ... | | | ... |
-------------------------------------------
^^^^^^^^^^^^^^^^^^^^^
recently created
x, x+1, ... y all points to the NULL
I want each space on recently created part point to NULL ?
This new space is part of the capacity of the vector, but not part of the size. You shouldn't need to care what values it contains, since you're not allowed to access it anyway. Other than the one value you pushed back, the extra space is not "elements of the vector", it's just unused space.
As far as the standard is concerned, the implementation could use it to store something meaningful, if it wanted. For example, an implementation could legally store some eye-catcher value in the unused memory, which conflicts with your desire for the unused memory to contain null pointers.
You could write code like this:
v.push_back(some_value);
if (v.capacity() > v.size()) {
size_t oldsize = v.size();
v.resize(v.capacity(), NULL);
v.resize(oldsize);
}
There's no guarantee this will actually leave the memory set to 0 once you resize back down again, but it probably will. So it might be good enough for debugging. If the purpose you have in mind is not debugging, please say what it is, because if not debugging then either your purpose is illegitimate or else one of us has misunderstood something.
If I correctly understood your question, one straightforward solution is to call resize() yourself passing NULL as second argument to be used as default value for newly created items:
if (v.size() == v.capacity()) //vector is full
{
//compute the new size
size_t newSize = 2 * v.size();
//second argument is the default value for newly added items
v.resize(newSize, NULL);
}
Why would you need it to be NULL unless it's been constructed? If you create a vector of 10 objects, say, and then push an extra, 11th item onto the vector then the vector may reserve enough space for another 10 items but you cannot use those items unless you either push items onto the vector increasing it's size, or you call resize.
size is not the same as capacity
Why would you need that? vector does not allow you to access these elements anyway. The expanding of it's capacity is implementation detail of vector and values of elements at the allocated space are not relevant. These elements will get overwritten once you push_back something there, or resize the vector with the given value.
There is an important difference between capacity and size of a vector.
When you push new elements into vector and there is no room, although std::vector allocates extra memory for new elements (similar to reserve() call), it does not create them (does not call constructors). See placement "new" to understand how this could work. There's no real way to enforce certain value for new elements, because there are no new elements - only raw memory block allocated for future elements. By using std::vector::at instead of operator[] you can ensure that you're accessing elements within valid range.
If you resize vector yourself by calling std::vector::resize, then simply provide default value for new elements in 2nd parameters. However, there's a catch. When you resize std::vector yourself and do not provide value for 2nd argument of std::vector::resize, std::vector will value-initialize new elements if value stored in std::vector has constructor and zero-initialize them otherwise. Which means, that if you do std::vector<int*> v; v.resize(200);, all new elements of v will be initialized to zero. See this answer for details.

How to remove elements from dynamically allocated array?

I have a dynamically allocated array :
myRectangle lastRectanglesArray = new myRectangle[lastMaxLabel];
I would like to loop through all elements in this array and remove these that will meet my condition (e.g. too big rectangle).
I have been thinking that I can loop through this array and get the number of elements that would satisfy my condition and then allocate a new array. But how can I 'transfer' these 'wanted' elements into my new array ?
Just for the record: I cannot use STL containers.
myRectangle * lastRectanglesArray = new myRectangle[lastMaxLabel];
// initialize the entries in the lastRectanglesArray
// create a temporary array which contains info about each individual
// entry. namely, it only holds info about whether the entry should
// be kept, or deleted.
// we also use the 'entries' value, which is the number of entries
// in the new array
bool * entriesToKeep = new bool[lastMaxLabel];
int entries = 0;
// check each entry, and mark whether it should be kept or deleted
for (int i = 0; i != lastMaxLabel; ++i) {
// check whether the entry should be kept or deleted...
// here, i just put a function with signature like:
// bool shouldKeepRectangle(const myRectangle &);
entriesToKeep[i] = shouldKeepRectangle(lastRectanglesArray[i]);
if (entriesToKeep[i]) ++entries;
}
// create a new array that will contain the entries that should be kept
myRectangle * rectanglesArray = new myRectangle[entries];
// assign the entries in the new array
for (int i = 0, j = 0; i != lastMaxLabel && j != entries; ++i) {
if (entriesToKeep[i])
rectanglesArray[j++] = lastRectanglesArray[i];
}
// free the memory held by the temp array
delete [] entriesToKeep;
// if the old array is not needed anymore, delete it
delete [] lastRectanglesArray;
// and here you have rectanglesArray, a brand new array that contains
// only the elements that you need.
Just move the next array location over the one that needs to be deleted, and shift everything over til the end of the array.
Yours look like the perfect case for using a Linked List. You would however have to do away with the new myRectangle[lastMaxLabel] part as you would have to implement it as pert of your Insert() function.
This way you would not require to transfer the wanted elements into a new array, but just delete the unwanted element.
Any more light on your use-case would help us to think of better alternatives.
I agree with Michael Chinen - use std::vector instead. You'll avoid lots of other potential problems this way. If you really want to use dynamic arrays, see this question: Remove an array element and shift the remaining ones
if you have a big amount of data in array that will be a problem for shifting using loop
maybe you should build your own array management class (find,add,deleteAt,etc).
my suggestion use link list node method.. it will be faster rather then you use loop for shifting.

Does the array key determine array size in C++?

im storing some settings for objects in an array. the id's of objects are used as the key. the id's start from 100000 and go up. if i was to input data for an object with id 100 000, would cpp automatical create 99999 blank key entries starting from 0?
Array size is determined when you create an array.
To access object at index 100 000 you need to have array of at least that size, which answers your question.
If the array is smaller you will access memory at
array begin address + (index*object
size)
which is not a good thing. E.g. the following will print some data but it is a data that are stored at that point in memory and it's outside of your array (not a good thing):
string arr[3];
cout << arr[5] << endl;
Assuming you are talking about standard array like:
string arr[10];
Array's size is specified when you compile it, for example you can't do:
string arr[]; // this will fail to compile, no size specified
But you do:
string arr[] = {"1","2","3"}; // array size is 3
string arr1[3]; // array size is 3
string arr2[3] = {"1"}; // array size is 3
If you want to map extra parameters for object you are better off using std::map like:
class person {};
std::map<person*,int> PersonScore;
This assumes that the additional parameters are not logically part of the object otherwise you would just add them to the object.
Maybe you want somthing along the lines of:
class ArrayPlus100k {
Item underlyingArray[NUM_ELEMENTS];
public:
Item& operator [] (int i) { return underlyingArray[i-100000]; }
// etc.
}
If you truely mean an array, and by key you mean index, then subtracting 100,000 from your index will provide you with a zero based array index. There will be no unused entries.
There may be a better container than a flat array. Choosing the right data structure depends on what you are trying to do. If you are storing objects using a key, you might want to use a std::map<key, value>.
What happens depends entirely on the data structure you choose to use. If you use a map, only the items you insert will take up space in memory. If you use new to allocate an actual array, then you will want to allocate only enough space for for the items you want to store. In that case, adjust your index by subtracting 100,000.
No, it will not create 0-99999, but rather start from 100000 to your array size.
For example, if you declare the following:
int arr[5];
Starting from arr[2], you can store up to arr[7].
I hope you understand...