Related
I would like to split the following sample array into arrays of array, where the sum of each sub array should not exceed 3 (here var sumMax).
Below is my current codes:
function splitArrByDuration(arr, sumMax) {
var sumMax = 3;
var arr = [["a", 2], ["b", 1], ["c", 2], ["d", 1]];
var splittedArr = [];
var temp_subArr = [];
if (arr.length) {
for (var i = 0; n = arr.length, i < n; i++) {
temp_subArr.push(arr[i]);
if (sumAtIndex(temp_subArr, index = 1) > sumMax && arr.length) {
var extraRow_temp_subArr = temp_subArr.splice(temp_subArr.length - 1, 1); //remove last element of "temp_subArr" because with it the sum will be greater than "sumMax"
//Logger.log(extraRow_temp_subArr);
arr.unshift(extraRow_temp_subArr[0]); //add the extra from temp_subArr to first index of "arr"
//i = i - 1;
splittedArr.push(temp_subArr);
temp_subArr = [];
}
}
}
Logger.log(splittedArr);
}
function sumAtIndex(arr, index = 1) {
var sumIndex = 0;
if (arr.length) {
for (var i = 0; n = arr.length, i < n; i++) {
sumIndex = sumIndex + arr[i][index];
}
}
//Logger.log(sumIndex);
return sumIndex;
}
The result from Logger.log(splittedArr) is currently : [[[a, 2.0], [b, 1.0]]]
What is expected should be [[[a, 2.0], [b, 1.0]], [[c, 2.0], [d, 1.0]]]
Can you please help me to get the right result?
Thanks in advance,
I thought that when I saw your script, it might be required to process the case that i is the last index. So, when your showing script is modified, how about the following modification?
Modified script:
function splitArrByDuration(arr, sumMax) {
var sumMax = 3;
var arr = [["a", 2], ["b", 1], ["c", 2], ["d", 1]];
var splittedArr = [];
var temp_subArr = [];
if (arr.length) {
for (var i = 0; n = arr.length, i < n; i++) {
temp_subArr.push(arr[i]);
if (sumAtIndex(temp_subArr, index = 1) > sumMax && arr.length) {
var extraRow_temp_subArr = temp_subArr.splice(temp_subArr.length - 1, 1); //remove last element of "temp_subArr" because with it the sum will be greater than "sumMax"
//Logger.log(extraRow_temp_subArr);
arr.unshift(extraRow_temp_subArr[0]); //add the extra from temp_subArr to first index of "arr"
//i = i - 1;
splittedArr.push(temp_subArr);
temp_subArr = [];
// Added
} else if (i == arr.length - 1) {
splittedArr.push(temp_subArr);
}
}
}
Logger.log(splittedArr);
}
Added:
From your following comment,
if I change var arr into var arr = [["a", 2], ["b", 1], ["c", 2], ["d", 1], ["e", 4]]; the script never stop to run.
In your script, when the value is ["e", 4], by arr.unshift(extraRow_temp_subArr[0]), arr is continued to be increased. By this, the infinite loop occurs. In order to achieve your new condition by modifying your script, I thought that it is required to add the process for checking the value of each element. The sample modified script is as follows.
Modified script:
function splitArrByDuration(arr, sumMax) {
var sumMax = 3;
var arr = [["a", 2], ["b", 1], ["c", 2], ["d", 1], ["e", 4]];
var splittedArr = [];
var temp_subArr = [];
if (arr.length) {
for (var i = 0; n = arr.length, i < n; i++) {
temp_subArr.push(arr[i]);
// Added
if (arr[i][1] >= sumMax) {
var t = temp_subArr.pop();
splittedArr.push(temp_subArr);
splittedArr.push([t]);
temp_subArr = [];
} else if (sumAtIndex(temp_subArr, index = 1) > sumMax && arr.length) {
var extraRow_temp_subArr = temp_subArr.splice(temp_subArr.length - 1, 1);
arr.unshift(extraRow_temp_subArr[0]);
splittedArr.push(temp_subArr);
temp_subArr = [];
// Added
} else if (i == arr.length - 1) {
splittedArr.push(temp_subArr);
}
}
}
Logger.log(splittedArr);
}
In this case, [[["a",2],["b",1]],[["c",2],["d",1]],[["e",4]]] is obtained.
There are a lot of methods to remove duplicates from an array in swift, but I'm trying to use a for in loop to manage that.
Can any one explain, why this code doesn't work?
Fatal error: Index out of range
func deleteDuplicates(array: [Int]) -> [Int] {
var newArray = array
for i in 0 ..< newArray.count - 1 {
for j in i + 1 ..< newArray.count {
if newArray[i] == newArray[j] {
newArray.remove(at: j)
}
}
}
return newArray
}
array1 = [0, 1, 8, 3, 4, 4, 3, 6, 7, 11, 4, 5, 5, 8]
deleteDuplicates(array: array1)
The problematic part is to iterate over an array and update that array at the same time. In this case, removing an element while iterating.
Removing an element decreases array length (count) and also changes indices. Therefore in
for j in i + 1 ..< array.count {
if array[i] == array[j] {
newArray.remove(at: j)
}
}
After removing the first index, your other indices become invalid. Note that count is always read only once, before the actual iteration.
This is one of the reasons why removing elements during iteration is dangerous and complicated. You could fix it by maintaining the number of removed elements and update indices accordingly. Or you can iterate backwards:
var newArray = array
for i in (0 ..< newArray.count - 1).reversed() {
for j in (i + 1 ..< newArray.count).reversed() {
if newArray[i] == newArray[j] {
newArray.remove(at: j)
}
}
}
return newArray
You are still changing indices and count but since you are iterating backwards, you only change the indices that have been already used.
In general it's simple and safer to build a new array instead of updating the current one:
var newArray: [Int] = []
for value in array {
if !newArray.contains(value) {
newArray.append(value)
}
}
return newArray
which can be very reduced in complexity (performance) by using a Set to keep added elements:
var newArray: [Int] = []
var foundElements: Set<Int> = []
for value in array {
if foundElements.insert(value).inserted {
newArray.append(value)
}
}
return newArray
Which can be simplified using filter:
var foundElements: Set<Int> = []
return array.filter { foundElements.insert($0).inserted }
One Reason is you are modifying the same array on which you are running two for loops. To understand in details, use the debugger as Martin says. And
This can be done using one for loop and Set:
var newArray = [0, 1, 8, 3, 4, 4, 3, 6, 7, 11, 4, 5, 5, 8]
var array = Set<Int>()
for i in newArray {
array.insert(i)
}
print(array)
output:
[4, 5, 3, 0, 1, 8, 6, 11, 7]
Here is one simple approach that you can try.
func removeDuplicates(_ nums: inout [Int]) {
var arrLen = nums.count
var index = 0
while(index < arrLen - 1){
if nums[index] == nums[index+1] {
nums.remove(at: index)
arrLen = arrLen - 1
}else{
index = index+1
}
}
}
It removes duplicates inplace without the need for new array being created.
I'm brand new to flutter and dart. I've searched google and all I can find is how to make 1d lists in flutter. I need a chart of values.
Specifically I need a row 12 long and a column 31 long filled with ascending numbers
1, 32, 63,
2, 33, 64,
3, 34, 65, etc....
thanks!
int row = 3;
int col = 4;
var twoDList = List.generate(row, (i) => List(col), growable: false);
//For fill;
twoDList[0][1] = "deneme";
print(twoDList);
// [[null, deneme, null, null], [null, null, null, null], [null, null, null, null]]
Your 2D list having 3 rows and 4 columns.
Declare and initialize a matrix x having m rows and n columns, containing real numbers.
var x = new List.generate(m, (_) => new List(n));
You can use smart_arrays_numerics package...
look at this..
https://pub.dev/packages/smart_arrays_numerics
else you should use nested list.
List<List<int>>
and create your list with generator
To get exactly what you want, you could use double List.generate, i.e.:
const cols = 31;
const rows = 12;
final array = List.generate(rows,
(i) => List.generate(cols + 1, (j) => i + j * cols + 1, growable: false),
growable: false);
array.forEach((row) {
print(row);
});
// [1, 32, 63, ...
// [2, 33, 64, ...
// [3, 34, 65, ...
// ...
There is also List.filled, where you can fill the array with some initial value when created. The following init the 2d array with 0s.
final array = List.generate(rows + 1, (i) => List.filled(cols + 1, 0, growable: false), growable: false);
To declare and initialize the array 2D in the dart, you can use:
List<List<int>> a =
[
[10, 2, 4, 6, -2],
[ 1, -16, 6, -2, -5],
[ 0, 3, 10, -5, 1],
[ 0, -4, 1, 18, 2],
[ 3, 1, 2, 2, -14],
];
#vahab
so would I do
final int NROWS = 12, NCOLS = 31;
List<Float64List> matrix = List(NROWS);
for (int i = 0; i < 373; i++) {
Float64List row = Float64List(NCOLS);
for (int k = 0; k < NCOLS; k++) { //I dont know what this does
row[k] = double.parse("$i.$k");
}
matrix[i] = row;
}
I would use a nested collection-for:
const maxRows = 31;
const maxColumns = 12;
var matrix = [
for (var row = 0; row < maxRows; row += 1)
[for (var column = 0; column < maxColumns; column += 1)
1 + row + column * maxRows],
];
Just use this statement i got this same problem, Got resolved
var list1 = List.generate(12,(i) => List.generate(31, (j) =>{Your equation to genearte })));
To initialize a 2d matrix filled with 0 :
List.generate(numberRows, (_) => List.filled(numberColumns, 0));
This question already has answers here:
Find min / max value in Swift Array
(16 answers)
Closed 1 year ago.
I am writing an algorithm to find the lowest number in an array however my print statement keeps saying that the lowest number is 0. I have the following:
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
func findMin(numbers: NSArray) {
var minValue = numbers[0]
var isSmallest: Bool
for i in 0...numbers.count {
isSmallest = true
for j in 0...numbers.count {
if i > j {
isSmallest = false
}
}
if isSmallest {
minValue = i
}
}
print("Smallest value in the list is \(minValue)")
}
findMin(numbers: list as NSArray)
My print statement returns as:
"Smallest value in the list is 0\n"
I feel like the algorithm is correct. Any ideas?
EDIT: Answered my own question
I was iterating over indices and not actual values. Thanks to one of the users in the comments. The correct code should be:
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
func findMin(numbers: NSArray) {
var minValue = numbers[0]
var isSmallest: Bool
for i in list {
isSmallest = true
for j in list {
if i > j {
isSmallest = false
}
}
if isSmallest {
minValue = i
}
}
print("Smallest value in the list is \(minValue)")
}
findMin(numbers: list as NSArray)
Simply
let list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
let minValue = list.min()
For logic use try this
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
var minValue = list[0]
for num in list {
minValue = (num < minValue) ? num : minValue
}
print("Smallest value in the list is \(minValue)")
For direct get min value by property
let list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
let minValue = list.min()
Or you could just use
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
list.min() // returns 2
If you'd like to find the min value without an extra loop, try this:
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
func findMin(numbers: NSArray) {
var minValIdx = 0
var minValue = numbers[0] as! Int
for i in 1..<numbers.count {
if (numbers[i] as! Int) < minValue {
minValue = numbers[i] as! Int
minValIdx = i
}
}
print("Smallest value in the list is \(minValue)")
}
findMin(numbers: list as NSArray)
You can use this code in Swift for manual algorithm:
let list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
var smallest = list[0]
for item in list {
if (item < smallest) {
smallest = item
}
}
print("smallest number is: \(smallest)")
And if you want Swift to do the hard work then use this:
let smallest = list.min()
print("smallest number is: \(smallest)")
here it is your solution
let numbers = [1, 6, 3, 9, 4, 6]
let min = minElement(numbers) // 1
let position = find(array, min)// it will return index
Just to throw a few more options out there, assuming you have to actually show some logic:
func min<T:Comparable>(_ elements:[T]) -> T? {
guard let first = elements[0] else {
return nil
}
return elements.reduce(first, min)
}
print(min(list))
or put it in an extension, this is essentially the definition of Array.min
extension Array where Element : Comparable {
func smallest() -> Element? {
guard let first = self.first else {
return nil
}
// Use 'Swift.min' to get to the global function since Array
// already has a min function
return reduce(first, Swift.min)
}
}
print(list.smallest())
You can use this code:
it is in C#
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
int minVal = list[0];
for (int i = 1; i < list.Length; i++)
{
if (list[i] < minVal)
{
minVal = intArray[i];
}
}
To find the minimum element in the sequence, Swift 3 have an istance method called min():
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
let minElem = list.min()
If the sequence has no elements, returns nil.
This method can be used also for a list of floats:
let heights = [67.5, 65.7, 64.3, 61.1, 58.5, 60.3, 64.9]
let minHeight = heights.min()
You can find the official document referece here
Ok so I have an array of websocket client connections. Imagine that this array contains connections to several different machines. Imagine that each different letter (1,2,3, etc) represents a different host. It might look like this:
const conns = [1,1,1,3,3,1,3,2,2,2,2,3,2,1,1,2,2];
what I would like to do, is sort the array like so:
const conns = [1,2,3,1,2,3,1,2,3, ... etc];
the rationale is if a client does not respond, I don't want to retry to the same host, I would like to try sending a message to a client on a different host, and only come back to the original host later. This is basically like a round-robin type thing.
I assume the best way to sort the array like this is:
find all the different hosts (unique letters) in the array
Iterate over this unique list, and splice off items from the original array as I go.
Here is the JS code I have for the above algorithm:
const list = [1,2,3,4,5,1,1,1,1,1,2,3,4,5,1,2,11,3,3,3,3,3,4,4,4,1,1,1];
const _ = require('lodash');
function findAndRemoveFirstMatch(m, list){
for(var i = 0; i < list.length; i++){
if(m === list[i]){
return list.splice(i,1)[0];
}
}
}
function getSorted(list){
const ret = [];
const set = _.uniqBy(list, function(x){
return x;
});
while(list.length > 0){
var i = 0;
while(i < set.length && list.length > 0){
var item;
if(item = findAndRemoveFirstMatch(set[i],list)){
ret.push(item);
}
i++;
}
}
return ret;
}
console.log(getSorted(list));
//given the above input, we get:
[ 1, 2, 3, 4, 5, 11, 1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 3, 4, 1, 3, 4, 1, 3, 1, 3, 1, 1, 1 ]
I am not proud of this code, and am wondering if there is a better way to do it. The above works for this input, but looking for a good way to clean it up and make it more generic.
Is there a better/faster way to do this?
You can do it differently:
sort input - it will help later
find maximum count of equal elements (10 in your example, for element=1), cnt
create cnt buckets to distribute elements over them
put elements in sorted order one by one into next bucket with round-robin principle
merge buckets
This way you get longer series in the end, 1 less than at the beginning.
[1, 2, 4, 1, 2, 4, 1, 2, 4, 1, 3, 4, 1, 3, 4, 1, 3, 5, 1, 3, 5, 1, 3, 11, 1, 3, 1, 3]
Bad case is when one element appears more than n/2 times, but that's unavoidable.
var list = [1,2,3,4,5,1,1,1,1,1,2,3,4,5,1,2,11,3,3,3,3,3,4,4,4,1,1,1];
var a = list.sort(function(a, b) { return a - b; });
var cnt = a.reduce(function(res, cur) {
if (cur == res[0])
return [cur, res[1]+1, Math.max(res[1]+1, res[2])]
else
return [cur, 1, Math.max(1, res[2])];
}, [null, 0, 0])[2];
var buckets = [];
for (var i = 0; i < cnt; i++)
buckets[i] = [];
var j = 0;
for (var i = 0; i < a.length; i++) {
buckets[j].push(a[i]);
j = (j+1)%cnt;
}
var res = buckets.reduce(function(r, cur) {
return r.concat(cur);
});
If you insist on full list of key from beginning, it's also possible:
var list = [1,2,3,4,5,1,1,1,1,1,2,3,4,5,1,2,11,3,3,3,3,3,4,4,4,1,1,1];
var a = list.sort(function(a, b) { return a - b; });
var cnt = a.reduce(function(res, cur) {
if (cur == res[0])
return [cur, res[1]+1, Math.max(res[1]+1, res[2])]
else
return [cur, 1, Math.max(1, res[2])];
}, [null, 0, 0])[2];
var buckets = [];
for (var i = 0; i < cnt; i++)
buckets[i] = [];
var j = 0;
var cur = null;
for (var i = 0; i < a.length; i++) {
if (cur != a[i])
j = 0;
buckets[j].push(a[i]);
j = j+1;
}
var res = buckets.reduce(function(r, cur) {
return r.concat(cur);
});