I have 2 lists:
distancestring[1][3], with the following values:
distancestring[0][0]=3.4
distancestring[0][1]=2
distancestring[0][2]=1.1
distancestring[1][0]=5
distancestring[1][1]=4.2
and imagestring[1][3], with the following values:
imagestring[0][0]="ccc"
imagestring[0][1]="aaa"
imagestring[0][2]="ddd"
imagestring[1][0]="bbb"
imagestring[1][1]="eee"
I would like to have a third list "result" with values of imagestring according to distancestring order.
Result should have items:
result[0][0]="ddd"
result[0][1]="aaa"
result[0][2]="ccc"
result[1][0]="eee"
result[1][1]="bbb"
Hope I made my self clear.
I am sure the following can be done more efficient but here is my suggestion on how it can be done.
Please note that it is important that distancestring and imagestring does have the same structure of elements like your example.
void main() {
final distancestring = [
[3.4, 2, 1.1],
[5, 4.2]
];
final imagestring = [
['ccc', 'aaa', 'ddd'],
['bbb', 'eee']
];
print(distancestring); // [[3.4, 2, 1.1], [5, 4.2]]
print(imagestring); // [[ccc, aaa, ddd], [bbb, eee]]
print(sort(
distancestring,
imagestring,
(dynamic d1, dynamic d2) =>
d1.compareTo(d2) as int)); // [[ddd, aaa, ccc], [eee, bbb]]
}
class Pair<A, B> {
final A a;
final B b;
const Pair(this.a, this.b);
}
List<List<B>> sort<A, B>(List<List<A>> distancestring,
List<List<B>> imagestring, int Function(A, A) compare) {
final temp = <Pair<A, B>>[];
for (var i = 0; i < distancestring.length; i++) {
for (var k = 0; k < distancestring[i].length; k++) {
temp.add(Pair(distancestring[i][k], imagestring[i][k]));
}
}
temp.sort((e1, e2) => compare(e1.a, e2.a));
var count = 0;
final result = <List<B>>[];
for (var i = 0; i < distancestring.length; i++) {
final list = <B>[];
for (var k = 0; k < distancestring[i].length; k++) {
list.add(temp[count++].b);
}
result.add(list);
}
return result;
}
Related
Here is my Dart code
var mp = new Map();
mp[[1,2]] = "Hi";
mp[[3,5]] = "sir";
mp.remove([3,5]);
print(mp);
Output here is null
How can i access value at mp[[3,5]]?
Two list instances containing the same elements is not equal to each other in Dart. This is the reason your example does not work.
If you want to create a Map which works like your example, you can use LinkedHashMap from dart:collection (basically the same when you are using Map()) to create an instance with its own definition of what it means for keys to be equal and how hashCode is calculated for a key.
So something like this if you want to have keys to be equal if the list contains the same elements in the same order. It should be noted it does not support nested lists:
import 'dart:collection';
void main() {
final mp = LinkedHashMap<List<int>, String>(
equals: (list1, list2) {
if (list1.length != list2.length) {
return false;
}
for (var i = 0; i < list1.length; i++) {
if (list1[i] != list2[i]) {
return false;
}
}
return true;
},
hashCode: Object.hashAll,
);
mp[[1, 2]] = "Hi";
mp[[3, 5]] = "sir";
mp.remove([3, 5]);
print(mp); // {[1, 2]: Hi}
}
I should also add that this is really an inefficient way to do use maps and I am highly recommend to never use List as keys in maps.
You add a list instance as a key to the Map object. You need the corresponding list instance to delete it again.
There are two ways to access
First;
final mp = {};
mp[[1,2]] = "Hi";
mp[[3,5]] = "sir";
mp.removeWhere((key, value) {
if(key is List){
return key.first == 3 && key[1] == 5;
}
return false;
});
Second;
final mp = {};
final key = [3, 5];
mp[[1,2]] = "Hi";
mp[key] = "sir";
mp.remove(key);
Map countries = {
"01": "USA",
"02": "United Kingdom",
"03": "China",
"04": "India",
"05": "Brazil",
"06": "Nepal",
"07": "Russia"
};
//method 1:
var _key = countries.keys.firstWhere((k)
=> countries[k] == 'Russia', orElse: () => null);
print(key); //output: 07
In my app, at many places I have used Lists like this:-
List<int> nums = [];
// initializing list dynamically with some values.
nums.length = 12; // increasing length of list
// setting these values afterward using nums[i] at different places.
Now after migrating to null-safety obviously nums.length = 4 is giving me a runtime error, so I was wondering is there any method to set the length of the list with default values such that, after if the length of the list was smaller than before then with new length extra elements are added with some default value.
Note: Of course I know we can use for loop, but I was just wondering if there is any easier and cleaner method than that.
var num = List<int>.generate(4, (i) => i);
You can read this.
Another approach:
extension ExtendList<T> on List<T> {
void extend(int newLength, T defaultValue) {
assert(newLength >= 0);
final lengthDifference = newLength - this.length;
if (lengthDifference <= 0) {
return;
}
this.addAll(List.filled(lengthDifference, defaultValue));
}
}
void main() {
var list = <int>[];
list.extend(4, 0);
print(list); // [0, 0, 0, 0];
}
Or, if you must set .length instead of calling a separate method, you could combine it with a variation of julemand101's answer to fill with a specified default value instead of with null:
class ExtendableList<T> with ListMixin<T> {
ExtendableList(this.defaultValue);
final T defaultValue;
final List<T> _list = [];
#override
int get length => _list.length;
#override
T operator [](int index) => _list[index];
#override
void operator []=(int index, T value) {
if (index >= length) {
_list.extend(index + 1, defaultValue);
}
_list[index] = value;
}
#override
set length(int newLength) {
if (newLength > length) {
_list.extend(newLength, defaultValue);
} else {
_list.length = newLength;
}
}
}
(I also made its operator []= automatically grow the ExtendableList if the specified index is out-of-bounds, similar to JavaScript.)
Your problem is that the List in Dart does not have the concept of adding more space while you promise that you are not going to use this new capacity before it is set.
But you can easily make your own List implementation which does this:
import 'dart:collection';
void main() {
List<int> nums = ExtendableList();
nums.length = 3;
nums[2] = 1;
nums[0] = 1;
nums[1] = 1;
print(nums); // [1, 1, 1]
nums.add(2);
print(nums); // [1, 1, 1, 2]
print(nums.runtimeType); // ExtendableList<int>
}
class ExtendableList<T> with ListMixin<T> {
final List<T?> _list = [];
#override
int get length => _list.length;
#override
T operator [](int index) => _list[index] as T;
#override
void operator []=(int index, T value) => _list[index] = value;
#override
set length(int newLength) => _list.length = newLength;
}
As you can see we are using a null type behind the scene but from the outside it will work like the list contains non-nullable. This only works because we assume the [] operator will not be called while a null value are in the list (which happens if we extend the list and does not set the value).
I should add that using such a List implementation does comes with great risk since you don't get any warning/error from the analyzer if you are using it wrongly.
You have to use a list of nullable element to make it longer.
List<int?> nums = [];
nums.length = 4; // OK
print(nums); // [null, null, null, null]
You can also use filled method. Here growable is false by default.
void main() {
var a = List<int>.filled(3, 0, growable: true);
print(a);
// [0, 0, 0]
}
Refer: https://api.flutter.dev/flutter/dart-core/List/List.filled.html
I am trying to write a script which displays the prime numbers from 0 to 100, but when I execute it, the browser crashes. JSHint didn't detect any error.
I'd like to learn why this code doesn't work: I am not interested in finding a totally different code( like this one) that completes the same task.
This is the first code I've ever written, so I apologise in advance for all the silly mistakes I overlooked.
var i;
var m;
var primeArr = [2, 3, 5, 7, 11, 13, 17, 19];
var theMaxNumber = 100;
var theMinNumber = 21;
var theCounter = -1;
function myFunction() {
for (i = theMinNumber; i < theMaxNumber; i += 2) {
for (m = 0; m < primeArr.length; m++) {
if (i % primeArr[m] !== 0) {
theCounter++;
if (theCounter === primeArr.length) {
primeArr.push(i);
}
if (m === primeArr.length) {
theCounter = -1;
}
}
}
}
console.log( primeArr.toString());
}
This is how it should work in theory:
1) the function finds out whether or not the number i is divisible for a prime number smaller then itself.
2) In case it is, theCounter is resetted and i is incremented by two.
3) In case it isn't, theCounter is incremented by one. If, at the end of the cycle, i is not divisibile for all the prime numbers smaller than itself, it means that it's a prime number: i is pushed in the array (because theCounter = == primeArr.length), then i is incremented by two.
edit: I fixed all the errors in the code, it works perfectly now:
var i;
var m;
var primeArr = [3, 5, 7, 11, 13, 17, 19];
var theMaxNumber = 100;
var theMinNumber = 21;
var theCounter = 0;
function myFunction() {
for (i = theMinNumber; i < theMaxNumber; i += 2) {
theCounter = 0;
for (m = 0; m < primeArr.length; m++) {
if (i % primeArr[m] !== 0) {
theCounter++;
}
if (theCounter === primeArr.length) {
primeArr.push(i);
}
}
}
primeArr.unshift(2);
console.log( primeArr.toString());
}
Your stop condition is wrong in the inner for loop it has an infinite loop increasing primeArr for ever until it crashes the JS engine.
Add an "alert" or "debugger" command to see the issue
for (m = 0; m < primeArr.length; m++) {
if (i % primeArr[m] !== 0) {
theCounter++;
if (theCounter === primeArr.length) {
primeArr.push(i);
}
Having trouble with a list function I wrote using CouchApp to take items from a view that are name, followed by a hash list of id and a value to create a CSV file for the user.
function(head, req) {
// set headers
start({ "headers": { "Content-Type": "text/csv" }});
// set arrays
var snps = {};
var test = {};
var inds = [];
// get data to associative array
while(row = getRow()) {
for (var i in row.value) {
// add individual to list
if (!test[i]) {
test[i] = 1;
inds.push(i);
}
// add to snps hash
if (snps[row.key]) {
if (snps[row.key][i]) {
// multiple call
} else {
snps[row.key][i] = row.value[i];
}
} else {
snps[row.key] = {};
snps[row.key][i] = row.value[i];
}
//send(row.key+" => "+i+" => "+snps[row.key][i]+'\n');
}
}
// if there are individuals to write
if (inds.length > 0) {
// sort keys in array
inds.sort();
// print header if first
var header = "variant,"+inds.join(",")+"\n";
send(header);
// for each SNP requested
for (var j in snps) {
// build row
var row = j;
for (var k in inds) {
// if snp[rs_num][individual] is set, add to row string
// else add ?
if (snps[j][inds[k]]) {
row = row+","+snps[j][inds[k]];
} else {
row = row+",?";
}
}
// send row
send(row+'\n');
}
} else {
send('No results found.');
}
}
If I request _list/mylist/myview (where mylist is the list function above and the view returns as described above) with ?key="something" or ?keys=["something", "another] then it works, but remove the query string and I get the error below:
{"code":500,"error":"render_error","reason":"function raised error: (new SyntaxError(\"JSON.parse\", \"/usr/local/share/couchdb/server/main.js\", 865)) \nstacktrace: getRow()#/usr/local/share/couchdb/server/main.js:865\n([object Object],[object Object])#:14\nrunList(function (head, req) {var snps = {};var test = {};var inds = [];while ((row = getRow())) {for (var i in row.value) {if (!test[i]) {test[i] = 1;inds.push(i);}if (snps[row.key]) {if (snps[row.key][i]) {} else {snps[row.key][i] = row.value[i];}} else {snps[row.key] = {};snps[row.key][i] = row.value[i];}}}if (inds.length > 0) {inds.sort();var header = \"variant,\" + inds.join(\",\") + \"\\n\";send(header);for (var j in snps) {var row = j;for (var k in inds) {if (snps[j][inds[k]]) {row = row + \",\" + snps[j][inds[k]];} else {row = row + \",?\";}}send(row + \"\\n\");}} else {send(\"No results found.\");}},[object Object],[object Array])#/usr/local/share/couchdb/server/main.js:979\n(function (head, req) {var snps = {};var test = {};var inds = [];while ((row = getRow())) {for (var i in row.value) {if (!test[i]) {test[i] = 1;inds.push(i);}if (snps[row.key]) {if (snps[row.key][i]) {} else {snps[row.key][i] = row.value[i];}} else {snps[row.key] = {};snps[row.key][i] = row.value[i];}}}if (inds.length > 0) {inds.sort();var header = \"variant,\" + inds.join(\",\") + \"\\n\";send(header);for (var j in snps) {var row = j;for (var k in inds) {if (snps[j][inds[k]]) {row = row + \",\" + snps[j][inds[k]];} else {row = row + \",?\";}}send(row + \"\\n\");}} else {send(\"No results found.\");}},[object Object],[object Array])#/usr/local/share/couchdb/server/main.js:1024\n(\"_design/kbio\",[object Array],[object Array])#/usr/local/share/couchdb/server/main.js:1492\n()#/usr/local/share/couchdb/server/main.js:1535\n#/usr/local/share/couchdb/server/main.js:1546\n"}
Can't say for sure since you gave little detail, however, a probable source of problems, is the use of arrays to collect data from every row: it consumes an unpredictable amount of memory. This may explain why it works when you query for a few records, and fails when you query for all records.
You should try to arrange data in a way that eliminates the need to collect all values before sending output to the client. And keep in mind that while map and reduce results are saved on disk, list functions are executed on every single query. If you don't keep list function fast and lean, you'll have problems.
I have a list of strings which I send to a queue. I need to split up the list so that I end up with a list of lists where each list contains a maximum (user defined) number of strings. So for example, if I have a list with the following A,B,C,D,E,F,G,H,I and the max size of a list is 4, I want to end up with a list of lists where the first list item contains: A,B,C,D, the second list has: E,F,G,H and the last list item just contains: I. I have looked at the “TakeWhile” function but am not sure if this is the best approach. Any solution for this?
You can set up a List<IEnumerable<string>> and then use Skip and Take to split the list:
IEnumerable<string> allStrings = new[] { "A", "B", "C", "D", "E", "F", "G", "H", "I" };
List<IEnumerable<string>> listOfLists = new List<IEnumerable<string>>();
for (int i = 0; i < allStrings.Count(); i += 4)
{
listOfLists.Add(allStrings.Skip(i).Take(4));
}
Now listOfLists will contain, well, a list of lists.
/// <summary>
/// Splits a <see cref="List{T}"/> into multiple chunks.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list">The list to be chunked.</param>
/// <param name="chunkSize">The size of each chunk.</param>
/// <returns>A list of chunks.</returns>
public static List<List<T>> SplitIntoChunks<T>(List<T> list, int chunkSize)
{
if (chunkSize <= 0)
{
throw new ArgumentException("chunkSize must be greater than 0.");
}
List<List<T>> retVal = new List<List<T>>();
int index = 0;
while (index < list.Count)
{
int count = list.Count - index > chunkSize ? chunkSize : list.Count - index;
retVal.Add(list.GetRange(index, count));
index += chunkSize;
}
return retVal;
}
Reference: http://www.chinhdo.com/20080515/chunking/
Some related reading:
Split a collection into `n` parts with LINQ?
Split List into Sublists with LINQ
LINQ Partition List into Lists of 8 members
Otherwise, minor variation on accepted answer to work with enumerables (for lazy-loading and processing, in case the list is big/expensive). I would note that materializing each chunk/segment (e.g. via .ToList or .ToArray, or simply enumerating each chunk) could have sideeffects -- see tests.
Methods
// so you're not repeatedly counting an enumerable
IEnumerable<IEnumerable<T>> Chunk<T>(IEnumerable<T> list, int totalSize, int chunkSize) {
int i = 0;
while(i < totalSize) {
yield return list.Skip(i).Take(chunkSize);
i += chunkSize;
}
}
// convenience for "countable" lists
IEnumerable<IEnumerable<T>> Chunk<T>(ICollection<T> list, int chunkSize) {
return Chunk(list, list.Count, chunkSize);
}
IEnumerable<IEnumerable<T>> Chunk<T>(IEnumerable<T> list, int chunkSize) {
return Chunk(list, list.Count(), chunkSize);
}
Test (Linqpad)
(note: I had to include the Assert methods for linqpad)
void Main()
{
var length = 10;
var size = 4;
test(10, 4);
test(10, 6);
test(10, 2);
test(10, 1);
var sideeffects = Enumerable.Range(1, 10).Select(i => {
string.Format("Side effect on {0}", i).Dump();
return i;
});
"--------------".Dump("Before Chunking");
var result = Chunk(sideeffects, 4);
"--------------".Dump("After Chunking");
result.Dump("SideEffects");
var list = new List<int>();
foreach(var segment in result) {
list.AddRange(segment);
}
list.Dump("After crawling");
var segment3 = result.Last().ToList();
segment3.Dump("Last Segment");
}
// test
void test(int length, int size) {
var list = Enumerable.Range(1, length);
var c1 = Chunk(list, size);
c1.Dump(string.Format("Results for [{0} into {1}]", length, size));
Assert.AreEqual( (int) Math.Ceiling( (double)length / (double)size), c1.Count(), "Unexpected number of chunks");
Assert.IsTrue(c1.All(c => c.Count() <= size), "Unexpected size of chunks");
}