I have a list of integers:
var times = [
1573613134,
1573623934,
1573631134,
1573659934,
1573746334,
1573731934,
1573764334,
1573789534,
1573847134,
1573933534,
1573893934,
1573980334,
1574153134,
1574178334
];
I would like to see if the values in this list are smaller than a specified integer.
var staticTime = [1573764334];
The easy, but time costly solution would be to use a for loop and compare every value within the list to staticTime.
Does Dart contain a built-in method to run basic inequality operations on a list of values?
Have you tried different methods to compare their speeds? The answer will probably surprise you. Take this quick benchmark, for example:
final values = <some list of numbers with values ranging from 0 to 1000000>;
void withForLoop() {
final start = DateTime.now();
final results = <int>[];
for (int i = 0; i < values.length; i++) {
if (values[i] < 500000) {
results.add(i);
}
}
final end = DateTime.now();
print('withForLoop method duration: ${end.difference(start)}');
}
void withForEachLoop() {
final start = DateTime.now();
final results = <int>[];
for (int v in values) {
if (v < 500000) {
results.add(v);
}
}
final end = DateTime.now();
print('withForEachLoop method duration: ${end.difference(start)}');
}
void withWhere() {
final start = DateTime.now();
final results = values.where((i) => i < 500000).toList();
final end = DateTime.now();
print('withWhere method duration: ${end.difference(start)}');
}
Running this script with value having a length of 1,000,000 resulted in these times on my computer:
withForLoop method duration: 0:00:00.125000
withForEachLoop method duration: 0:00:00.129000
withWhere method duration: 0:00:00.470000
From this, several things can be deduced:
The regular for loop completed the fastest.
The iterator-based "for-each" loop was only slightly slower than the for loop. (3.2% slower)
The generator-based where method was by far the slowest. (276% slower)
All three completed remarkably fast given the sample size, particularly considering a good chunk of the execution time was likely due to the resizing and reallocation of the result list due to the add call (the where method doesn't do this explicitly in the code shown, but it does happen internally).
The generator methods (e.g. map, where, reduce, etc.) are good because of their convenience, not because of their speed. In terms of raw performance, the bog-standard for loop will almost always be the fastest (ignoring some fairly technical tricks possible in some low-level languages, most of which cannot be done in Dart). That being said, it took a list of a million elements or more for any of the attempts to take any appreciable amount of time, and chances are any application you make in Dart isn't going to deal with data sets anywhere close to that big. For data sets of a more reasonable size, any of the above attempts will likely be more than fast enough for your purposes.
If you learned anything from this answer, hopefully it was these two things:
Don't prematurely criticize the performance of certain patterns until you've benchmarked them yourself. (More often than not, your assumptions may be wrong.)
Don't worry about the performance of things that are inherently insanely fast. (Other parts of your program will bottleneck long before this does.)
(If you want to try the above code for yourself, try it out in DartPad.)
There is the built-in every() function.
var allSmaller = times.every((time) => time > staticTime);
If you want to know whether there is any value smaller than staticTime then use:
bool hasAnySmaller = times.any((time)=> time<staticTime);
If you want the list of integers smaller than the staticTime then use:
List<int> allSmaller = times.where((time)=>time<staticTime).toList();
Related
My question will seem quite simple, but I'm having a hard time understanding how certain queries work with ObjectBox and Flutter.
I have a List object. I would like to retrieve them all, but display only the first 5, sorted by ascending name.
I find many examples with filter queries in the documentation, but the getAll() does not allow to easily integrate the limit and I find very few examples. I think I'm doing it wrong. What is the best way to do this query ?
final boxListCoins = objectBoxDatabase.store.box<CoinsList>();
// final query = boxListCoins.getAll(); ?
final query = (boxListCoins.query()..order(CoinsList_.coinId, flags: Order.descending)).build();
query.limit = 5;
final coinsList = query.find();
I see that you want to get all your results but you want to display the first 5. So what I would do in your case is:
(1) get all your results(based on your query)
(2) then set another property equal to the top 5:)
** now you have a list of all your entries and you have your top 5 that you can display.
heres how I would code it up!
final boxListCoins = objectBoxDatabase.store.box<CoinsList>();
// final query = boxListCoins.getAll(); ?
final query = (boxListCoins.query()..order(CoinsList_.coinId, flags: Order.descending)).build();
// this is your list of all of the coins!
final coinsList = query.find();
// This is you list of the Top 5
var topFive = [];
if (coinsList.length >= 5) {
// take your top5 here :) also feel free to turn this iterable into what ever you want I just choose to keep it a list :)
topFive = coinsList.take(5).toList();
} else {
// if you length is not greater than 5 then you have your top automatically.
topFive = coinsList;
}
Hope this helps:)
Happy Coding, also I'm a developer #Pieces and if you need a place to store helpful code snippets, like this one, check it out here https://code.pieces.app/
I have a big list of 50k lines. Now when I try to sort it with list.sort it throws Stack Overflow error.
How to make the sorting work lazily without filling the stack?
List<List<dynamic>> sortData(List<List<dynamic>> data,
{int sortItemNumber = 4}) {
data.sort((List<dynamic> a, List<dynamic> b) {
return compare(a[sortItemNumber], b[sortItemNumber]);
});
return data;
}
int compare(var itemA, var itemB) {
if (itemA.runtimeType == String || itemB.runtimeType == String) {
return -1;
}
return itemA.compareTo(itemB);
}
Your compare function always returns -1 for certain inputs. Those inputs can't be sorted, because there's no way to know if an element comes before or after anything else - you're saying a<b and b<a are both simultaneously true. So the sort fails. Different sorting algorithms will fail in different ways, yours evidently generates a stack overflow probably due to infinite recursion.
Since you say this is just for testing at the moment, you could try replacing with return 0 to indicate those items are equivalent and thus already in the proper order. The sort will still be incorrect, but it probably won't crash any more.
I've got an interesting question for Rx experts. I've a relational table keeping information about events. An event consists of id, type and time it happened. In my code, I need to fetch all the events within a certain, potentially wide, time range.
SELECT * FROM events WHERE event.time > :before AND event.time < :after ORDER BY time LIMIT :batch_size
To improve reliability and deal with large result sets, I query the records in batches of size :batch_size. Now, I want to write a function that, given :before and :after, will return an Observable representing the result set.
Observable<Event> getEvents(long before, long after);
Internally, the function should query the database in batches. The distribution of events along the time scale is unknown. So the natural way to address batching is this:
fetch first N records
if the result is not empty, use the last record's time as a new 'before' parameter, and fetch the next N records; otherwise terminate
if the result is not empty, use the last record's time as a new 'before' parameter, and fetch the next N records; otherwise terminate
... and so on (the idea should be clear)
My question is:
Is there a way to express this function in terms of higher-level Observable primitives (filter/map/flatMap/scan/range etc), without using the subscribers explicitly?
So far, I've failed to do this, and come up with the following straightforward code instead:
private void observeGetRecords(long before, long after, Subscriber<? super Event> subscriber) {
long start = before;
while (start < after) {
final List<Event> records;
try {
records = getRecordsByRange(start, after);
} catch (Exception e) {
subscriber.onError(e);
return;
}
if (records.isEmpty()) break;
records.forEach(subscriber::onNext);
start = Iterables.getLast(records).getTime();
}
subscriber.onCompleted();
}
public Observable<Event> getRecords(final long before, final long after) {
return Observable.create(subscriber -> observeGetRecords(before, after, subscriber));
}
Here, getRecordsByRange implements the SELECT query using DBI and returns a List. This code works fine, but lacks elegance of high-level Rx constructs.
NB: I know that I can return Iterator as a result of SELECT query in DBI. However, I don't want to do that, and prefer to run multiple queries instead. This computation does not have to be atomic, so the issues of transaction isolation are not relevant.
Although I don't fully understand why you want such time-reuse, here is how I'd do it:
BehaviorSubject<Long> start = BehaviorSubject.create(0L);
start
.subscribeOn(Schedulers.trampoline())
.flatMap(tstart ->
getEvents(tstart, tstart + twindow)
.publish(o ->
o.takeLast(1)
.doOnNext(r -> start.onNext(r.time))
.ignoreElements()
.mergeWith(o)
)
)
.subscribe(...)
Consider the below program
private static bool CheckFactorPresent(List<FactorReturn> factorReturnCol)
{
bool IsPresent = true;
StringBuilder sb = new StringBuilder();
//Get the exposure names from Exposure list.
//Since this will remain same , so it has been done outside the loop
List<string> lstExposureName = (from item in Exposures
select item.ExposureName).ToList<string>();
foreach (FactorReturn fr in factorReturnCol)
{
//Build the factor names from the ReturnCollection dictionary
List<string> lstFactorNames = fr.ReturnCollection.Keys.ToList<string>();
//Check if all the Factor Names are present in ExposureName list
List<string> result = lstFactorNames.Except(lstExposureName).ToList();
if (result.Count() > 0)
{
result.ForEach(i =>
{
IsPresent = false;
sb.AppendLine("Factor" + i + "is not present for week no: " + fr.WeekNo.ToString());
});
}
}
return IsPresent;
}
Basically I am checking if all the FactorNames[lstFactorNames] are present in
ExposureNames[lstExposureName] list by using lstFactorNames.Except(lstExposureName).
And then by using the Count() function(if count() > 0), I am writing the error
messages to the String Builder(sb)
I am sure that someone can definitely write a better implementation than the one presented.
And I am looking forward for the same to learn something new from that program.
I am using c#3.0 and dotnet framework 3.5
Thanks
Save for some naming convention issues, I'd say that looks fine (for what I can figure out without seeing the rest of the code, or the purpose in the effort. The naming conventions though, need some work. A sporadic mix of ntnHungarian, PascalCase, camelCase, and abbrv is a little disorienting. Try just naming your local variables camelCase exclusively and things will look a lot better. Best of luck to you - things are looking good so far!
- EDIT -
Also, you can clean up the iteration at the end by just running a simple foreach:
...
foreach (var except in result)
{
isPresent = false;
builder.AppendFormat("Factor{0} is not present for week no: {1}\r\n", except, fr.WeekNo);
}
...
I've got a piece of code that opens a data reader and for each record (which contains a url) downloads & processes that page.
What's the simplest way to make it multi-threaded so that, let's say, there are 10 slots which can be used to download and process pages in simultaneousy, and as slots become available next rows are being read etc.
I can't use WebClient.DownloadDataAsync
Here's what i have tried to do, but it hasn't worked (i.e. the "worker" is never ran):
using (IDataReader dr = q.ExecuteReader())
{
ThreadPool.SetMaxThreads(10, 10);
int workerThreads = 0;
int completionPortThreads = 0;
while (dr.Read())
{
do
{
ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
if (workerThreads == 0)
{
Thread.Sleep(100);
}
} while (workerThreads == 0);
Database.Log l = new Database.Log();
l.Load(dr);
ThreadPool.QueueUserWorkItem(delegate(object threadContext)
{
Database.Log log = threadContext as Database.Log;
Scraper scraper = new Scraper();
dc.Product p = scraper.GetProduct(log, log.Url, true);
ManualResetEvent done = new ManualResetEvent(false);
done.Set();
}, l);
}
}
You do not normally need to play with the Max threads (I believe it defaults to something like 25 per proc for worker, 1000 for IO). You might consider setting the Min threads to ensure you have a nice number always available.
You don't need to call GetAvailableThreads either. You can just start calling QueueUserWorkItem and let it do all the work. Can you repro your problem by simply calling QueueUserWorkItem?
You could also look into the Parallel Task Library, which has helper methods to make this kind of stuff more manageable and easier.