First of all this is a common question not related to the Dart
language, but because I need it for Dart, I tagged it like so.
I have a List of objects which contain an incremental number
List<MyObject> myObjectList = [
MyObject(1),
MyObject(2),
...
MyObject(10),
];
class MyObject {
int order;
MyObject(this.order);
}
I now want to remove an item from the List and the following order numbers to decrease. So lets say I remove item with order number 5, the ones with 6, 7, 8, 9 and 10 should decrement by one, resulting in a List like:
List<MyObject> myObjectList = [
MyObject(1),
MyObject(2),
...
MyObject(9),
];
This can easily be done with a for-loop checking the items number:
var removedOrder = 5;
for (var item in myObjectList){
if (item.order > removedOrder) {
item.order -= 1;
}
}
This is really simple to understand and should work, but honestly, simple is boring and ugly.
Is there a way to achieve the desired result without the need to write a for loop?
Also what are your suggestions to optimize that logical part?
One solution would be: When you delete and item from the list on position lets say 5, then you can take the last item in the list and change its value to 5. This removes the need to run through all the items and decreasing its values.
Related
For example if I have a vector of ints
vector<int> my_vector;
my_vector[0] = 6;
my_vector[1] = 3;
So my vector is of size 2 right now.
Now let's say I want to add another integer in my vector. Let's just say this new integer is 10.
I want to be able to set it up 3 (my_vec.size() + 1) ways. In other words, check where placing my new value in my vector of ints would result in the value I'm interested in.
10, 6, 3
6, 10, 3
6, 3, 10
Out of those 3 options, I'll pick the one that best fits my needs. The one I pick, will be my new vector. So if I pick 6, 10, 3, that will be my vector afterwards.
That's the gist of what I want to be able to do.
I have a very inefficient brute force way of creating temp vectors and calculating it that way. I was wondering if there is a simple and optimal way to go about this. I essentially want to be able to compute a new value that I want to add into my vector in all possible areas and look for whatever value I'm interested in.
Just insert new element to the end (most efficient way for the vector) and then move it to the front step by step and test each combination:
vec.push_back( new_value );
test_vector( vec );
for( size_t i = vec.size() - 1; i > 0; --i ) {
std::swap( vec[i], vec[i-1] );
test_vector( vec );
}
live example on ideone for 6,3 + 10. New element will always end at the first position. You need to find best position and then move your element there, that should be pretty obvious.
You really only have 2 cases here. First case: the newly added number is less than the first number in the vector. In this case the number should always be added to the beginning of the vector. If the new number is larger, it should always go in the second spot in the vector (since moving it any farther down the vector will not affect the new total).
I guess I understand your question.
Your computing method is complex. It is a example just now.
Only can you pick a kind of arrangement?
You can implement a function like this:
int GetArrangemnetValue(vector<int>& sourceVec, int nNewPos, int nNewValue);
This function to simulate a whole vetor.
You can do some compute is this function.
Then you can do some select via the return value of funtion.
So you can use this function and not a temporary vector.
This is not similar to Can you remove elements from a std::list while iterating through it?. Mine is a different scenario.
Lets say I have a list like this.
1 2 3 1 2 2 1 3
I want to iterate this stl list in such a way that
When I first encounter an element X I do some activity and then I need to remove all the elements X in that list and continue iterating. Whats an efficient way of doing this in c++.
I am worried that when i do a remove or an erase I will be invalidating the iterators. If it was only one element then I could potentially increment the iterator and then erase. But in my scenario I would need to delete/erase all the occurances.
Was thinking something like this
while (!list.empty()) {
int num = list.front();
// Do some activity and if successfull
list.remove(num);
}
Dont know if this is the best.
Save a set of seen numbers and if you encounter a number in the set ignore it. You can do as follows:
list<int> old_list = {1, 2, 3, 1, 2, 2, 1, 3};
list<int> new_list;
set<int> seen_elements;
for(int el : old_list) {
if (seen_elements.find(el) == seen_elements.end()) {
seen_elements.insert(el);
new_list.push_back(el);
}
}
return new_list;
This will process each value only once and the new_list will only contain the first copy of each element in the old_list. This runs in O(n*log(n)) because each iteration performs a set lookup (you can make this O(n) by using a hashset). This is significantly better than the O(n^2) that your approach runs in.
In this project, there are multiple sets in which they hold values from 1 - 9. Within this, I need to efficiently determine if there are values that is unique in one set but not others.
For Example:
std::set<int> s_1 = { 1, 2, 3, 4, 5 };
std::set<int> s_2 = { 2, 3, 4 };
std::set<int> s_3 = { 2, 3, 4, 6 };
Note: The number of sets is unknown until runtime.
As you can see, s_1 contains the unique value of 1 and 5 and s_3 contains the unique value of 6.
After determining the unique values, the aforementioned sets should then just contain the unique values like:
// s_1 { 1, 5 }
// s_2 { 2, 3, 4 }
// s_3 { 6 }
What I've tried so far is to loop through all the sets and record the count of the numbers that have appeared. However I wanted to know if there is a more efficient solution out there.
There are std algorithm in the std C++ library for intersection, difference and union operations on 2 sets.
If I understood well your problem you could do this :
do an intersection on all sets (in a loop) to determine a base, and then apply a difference between each set and the base ?
You could benchmark this against your current implementation. Should be faster.
Check out this answer.
Getting Union, Intersection, or Difference of Sets in C++
EDIT: cf Tony D. comment : You can basically do the same operation using a std::bitset<> and binary operators (& | etc..), which should be faster.
Depending on the actual size of your input, might be well worth a try.
I would suggest something in c# like this
Dictionary<int, int> result = new Dictionary<int, int>();
foreach(int i in sets){
if(!result.containskey(i))
result.add(i,1);
else
result[i].value = result[i].value+1;
}
now the Numbers with count value only 1 means its unique, then find the sets with these numbers...
I would suggest :
start inserting all the elements in all the sets into a multimap.
Here each element is a key and and the set name with be the value.
One your multimap is filled with all the elements in all the sets,
then loop throgth the multimap and take count of each element in the
multimap.
If the count is 1 for any key, this means its unique and value of
that will be the set name.
I have a list of integers and I need to find out the range it falls in. I have a list of ranges which might be of size 2 to 15 at the maximum. Currently for every integer,I check through the list of ranges and find its location. But this takes a lot of time as the list of integers I needed to check includes few thousands.
//list of integers
val numList : List[(Int,Int)] = List((1,4),(6,20),(8,15),(9,15),(23,27),(21,25))
//list of ranges
val rangesList:List[(Int,Int)] = List((1,5),(5,10),(15,30))
def checkRegions(numPos:(Int,Int),posList:List[(Int,Int)]){
val loop = new Breaks()
loop.breakable {
for (va <- 0 until posList.length) {
if (numPos._1 >= posList(va)._1 && numPos._2 <= (posList(va)._2)) {
//i save "va"
loop.break()
}
}
}
}
Currently for every integer in numList I go through the rangesList to find its range and save its range location. Is there any faster/better way approach to this issue?
Update: It's actually a list of tuples that is compared against a list of ranges.
First of all, using apply on a List is problematic, since it takes linear run time.
List(1,2,3)(2) has to traverse the whole list to finally get the last element at index 2.
If you want your code to be efficient, you should either find a way around it or choose another data structure. Data structures like IndexedSeq have constant time indexing.
You should also avoid breaks, as to my knowledge, it works via exceptions and that is not a good practice. There are always ways around it.
You can do something like this:
val numList : List[(Int,Int)] = List((1,4),(6,20),(8,15),(9,15),(23,27),(21,25))
val rangeList:List[(Int,Int)] = List((1,5),(5,10),(15,30))
def getRegions(numList: List[(Int,Int)], rangeList:List[(Int,Int)]) = {
val indexedRangeList = rangeList.zipWithIndex
numList.map{case (a,b) => indexedRangeList
.find{case ((min, max), index) => a >= min && b <= max}.fold(-1)(_._2)}
}
And use it like this:
getRegions(numList, rangeList)
//yields List(0, -1, -1, -1, 2, 2)
I chose to yield -1 when no range matches. The key thing is that you zip the ranges with the index beforehand. Therefore we know at each range, what index this range has and are never using apply.
If you use this method to get the indices to again access the ranges in rangeList via apply, you should consider changing to IndexedSeq.
The apply will of course only be costly when the number ranges gets big. If, as you mentioned, it is only 2-15, then it is no problem. I just want to give you the general idea.
One approach includes the use of parallel collections with par, and also indexWhere which delivers the index of the first item in a collection that holds a condition.
For readability consider this predicate for checking interval inclusion,
def isIn( n: (Int,Int), r: (Int,Int) ) = (r._1 <= n._1 && n._2 <= r._2)
Thus,
val indexes = numList.par.map {n => rangesList.indexWhere(r => isIn(n,r))}
indexes: ParVector(0, -1, -1, -1, 2, 2)
delivers, for each number, the index in the ranges collection where it is included. Value -1 indicates the condition did not hold.
For associating numbers with range indexes, consider this,
numList zip indexes
res: List(((1,4), 0), ((6,20),-1), ((8,15),-1),
((9,15),-1), ((23,27),2), ((21,25),2))
Parallel collections may prove more efficient that the non parallel counterpart for performing computations on a very large number of items.
I am working on the following task:
For every item in list1 find first n best matches for item in list2
Items themselves are fairly big (around 1.5 kb each), and there is a function for their comparison.
What I have been doing till now, can be expressed in following pseudocode:
for every item1 in list1 {
for every item2 in list2 {
put index of item2 in index_buffer
put match(item1,item2) in value_buffer
}
sort index_buffer by value_buffer
put first n of index from index_buffer, value_buffer(index) in result_ buffer
}
I wonder, what are better/faster ways to do that.
The language I am using is c++, with Qt as a framework. I know for sure that the same task with same data is executed 4 times faster in matlab, which shouldn't be the case.
Here is relevant code: http://pastebin.com/xsWsWzgp
There's a faster way to do your step 2. Actually, you combine it with step 1.
Right now you keep all the results, sort them, and pick the top N to put in the output buffer. What you could do instead is create a priority queue that holds N items, and just keep the top N found so far. In pseudocode, it looks something like this:
for every item1 in list1
{
create empty priority queue to hold n items
for every item2 in list2
{
value = match(item1, item2)
if priorityqueue length < n
add value and index to priority queue
else if value > lowest value currently in priority queue
{
remove lowest value from priority queue
add new value and index to priority queue
}
}
add items from priority queue to result buffer
}
Look into the STL std::priority_queue.
If the number of items requested (n) is much smaller than the length of list2, that will save you a lot of time.
As somebody else pointed out, it might be reasonable to remove items from list2 (or somehow flag them) when they match, so that they won't be matched again. Unless of course you want and expect duplicate matches.