slice to create 2 dimensional array - reactjs

I want to create a 2 dimensional array
array items has 32 objects
every array contains 9 objects each with the remainder (32 % 9 = 5) in the last array
with the code below, I am expecting :
I am expecting : [Array(9), Array(9), Array(9), Array(5)]
const returnProductsArrays = (items) => {
let TwoDimensionalArray = []
let remainder = items.length % 9
let i = 0
while (i < (items.length - remainder)) {
let array = items.slice(i, 9)
TwoDimensionalArray.push(array)
i += 9
}
const array = items.slice(i + 1, remainder)
TwoDimensionalArray.push(array)
return TwoDimensionalArray
}
only the 1st array has objects, the rest is empty.
What am I am missing ?
slice does not mutate vs. splice . why is the array empty on the 2 iteration in the while loop

there are two mistakes, I will point below:
const returnProductsArrays = (items) => {
let TwoDimensionalArray = []
let remainder = items.length % 9
let i = 0
while (i < (items.length - remainder)) {
// second param needs to be "i + 9"
let array = items.slice(i, i + 9)
TwoDimensionalArray.push(array)
i += 9
}
// here you need just the "i" param (not i+1), and it will slice till the end of array
const array = items.slice(i)
TwoDimensionalArray.push(array)
return TwoDimensionalArray
}

Related

Count hashmap elements with condition for members? [duplicate]

I'm basically looking for the swift equivalent of the follow c++ code:
std::count_if(list.begin(), list.end(), [](int a){ return a % 2 == 0; }); // counts instances of even numbers in list
My problem isn't actually searching for even numbers, of course; simply the general case of counting instances matching a criterion.
I haven't seen a builtin, but would love to hear that I simply missed it.
Like this:
let a: [Int] = ...
let count = a.filter({ $0 % 2 == 0 }).count
An alternative to Aderstedt's version
let a = [ .... ]
let count = a.reduce(0){
(count, element) in
return count + 1 - element % 2
}
My intuition says my way will be faster because it doesn't require the creation of a second array. However, you'd need to profile both methods to be sure.
Edit
Following MartinR's comment about generalisation of the function, here it is
extension SequenceType
{
func countMatchingCondition(condition: (Self.Generator.Element) -> Bool) -> Int
{
return self.reduce(0, combine: { (count, e) in count + (condition(e) ? 1 : 0) })
}
}
let a = [1, 2, 3, 3, 4, 12].countMatchingCondition { $0 % 2 == 0 }
print("\(a)") // Prints 3
Default array:
let array: [Int] = [10, 10, 2, 10, 1, 2, 3]
filter(_:) method
let countOfTen = array.filter({ $0 == 10 }).count // 3
count(where:) method
Update: This Swift 5.0 feature was withdrawn in beta testing because it was causing performance issues for the type checker.
let countOfTen = array.count(where: { $0 == 10 }) // 3
You can use Collection.lazy to have the simplicity of Aderstedt's Answer but with O(1) space.
let array = [1, 2, 3]
let count = array.lazy.filter({ $0 % 2 == 0 }).count
The most compact reduce statement that will do this is:
let a = Array(1 ... 20)
let evencount = a.reduce(0) { $0 + ($1 % 2 == 0 ? 1 : 0) }
Reduce takes two variables: starts with 0 (var $0) then for every element in Array a (var $1) if the value is divisible by 2 with no remainder then add one to your count.
This is also efficient as it does not create an additional array unlike using a.filter(){}.count .
You can also do this with reduce()
let a = Array(1 ... 20)
let evenCount = a.reduce(0) { (accumulator, value) -> Int in
guard value % 2 == 0 else { return accumulator }
return accumulator + 1
}
Almost everything you want to do with the map() and filter functions can actually be done with a reduce although it's not always the most readable.
Swift 5 or later:
public extension Sequence {
func occurrences(where predicate: (Element) throws -> Bool) rethrows -> Int {
try reduce(0) { try predicate($1) ? $0 + 1 : $0 }
}
}
public extension Sequence where Element: Equatable {
func occurrences(of element: Element) -> Int {
reduce(0) { element == $1 ? $0 + 1 : $0 }
}
}
let multiplesOf2 = [1,2,3,4,4,5,4,5].occurrences{$0.isMultiple(of: 2)} // 4
"abcdeabca".occurrences(of: "a") // 3
extension BinaryInteger {
var isOdd: Bool { !isMultiple(of: 2) }
var isEven: Bool { isMultiple(of: 2) }
}
(-4).isOdd // false
(-3).isOdd // true
(-2).isOdd // false
(-1).isOdd // true
0.isOdd // false
1.isOdd // true
2.isOdd // false
3.isOdd // true
4.isOdd // false
(-4).isEven // true
(-3).isEven // false
(-2).isEven // true
(-1).isEven // false
0.isEven // true
1.isEven // false
2.isEven // true
3.isEven // false
4.isEven // true
let odds = [1,2,3,4,4,5,5,11].occurrences(where: \.isOdd) // 5
let evens = [1,2,3,4,4,5,5,11].occurrences(where: \.isEven) // 3

Obtain values that match in two different arrays in Swift

In a service request, I obtain an array with this structure:
(
{
key = 1;
val = "Cookies";
},
{
key = 2;
val = Restaurante;
},
{
key = 22;
val = "Cereals";
},
{
key = 16;
val = "Shirts";
}
In a second request, I obtain another array of values that are related to the array of the first request:
▿ Optional<NSArray>
▿ some : 5 elements
- 0 : 1
- 1 : 2
- 2 : 5
- 3 : 19
- 4 : 20
What I need is to show in a tableView the text of the first array whose keys I obtain in the second array, how could I do that?
It looks like you obtain that types of arrays
struct ArrayObject {
let key: Int
let value: String
}
let objectArray: [ArrayObject] = []
let keysArray: [Int] = []
Then you need to use filter to determine what keys are contains in second array:
// if you need objects
let filteredObjectsResult = objectArray.filter { keysArray.contains($0.key) }
// if you need values only
let filteredValuesResult = filteredObjectsResult.map { $0.value }

Shallow copy an array/modify arrays based on condition in swift

var a=[0,0,0,0]
var b=[0,0,0,0]
for i in 0..<4{
var g=i%2==0 ? a:b
g[i]+=1
//10 more lines of code about array g
}
I want to implement something like whenever i is an even number increment the i position of A by 1, and if i is odd increment the i position of B by 1.
The expecting result is A=[1,0,1,0] and B is [0,1,0,1]
Here modifying the array g will not affect the original array because of deep copy. Are there any ways to modify array a and b without using if...else statement?
You have to modify a value type directly, a possible solution is
var a = [0,0,0,0]
var b = [0,0,0,0]
for i in 0..<4 {
i.isMultiple(of: 2) ? (a[i] += 1) : (b[i] += 1)
}
Another solution is to use a class (reference type) wrapper
class Wrapper {
var array = [0,0,0,0]
}
let a = Wrapper()
let b = Wrapper()
for i in 0..<4 {
let g = i.isMultiple(of: 2) ? a : b
g.array[i] += 1
}
print(a.array)
print(b.array)
var a=[0,0,0,0]
var b=[0,0,0,0]
for i in 0..<4{
i%2==0 ? (a[i] += 1) : (b[i] += 1)
}
print(a)
print(b)
Result A=[1,0,1,0] B = [0,1,0,1]
You could use a function with an inout parameter:
func modify(g: inout [Int], index: Int) {
g[index] += 1
// 10 more lines of code about array g
}
var a = [0,0,0,0]
var b = [0,0,0,0]
for i in 0..<4 {
if i.isMultiple(of: 2) {
modify(g: &a, index: i)
} else {
modify(g: &b, index: i)
}
}
print(a)
print(b)
You could also put the arrays into a class (reference type) and use that reference to access the array instead of trying to reference the arrays (value types) directly.
See inout documentation here
Some info on value vs reference types
You are not "thinking value type", yet. For those, copy, modify, and reassign.
var array: [Int] { .init(repeating: 0, count: 4) }
let (a, b) = array.indices.reduce( into: (array, array) ) { arrays, index in
let indexIsEven = index.isMultiple(of: 2)
// Copy
var array = indexIsEven ? arrays.0 : arrays.1
// Modify
array[index] = 1
// Reassign
indexIsEven
? (arrays.0 = array)
: (arrays.1 = array)
}

Swift array remove consecutive numbers via filter

How it is possible to write filter function that will remove consecutive numbers from array.
By consecutive I mean 1,2,3,4 form a sequence contrary to 1,3,5 (missing the 2 and 5).
Example:
let input = [1,2,3,4,8,10,12,19]
//Expected filter function.
let output = [8,10,12,19]
You can use flatMap which acts as a map and a filter against nil:
let output = input.enumerated().flatMap { index, element in
return index > 0 && input[index - 1] + 1 == element ? nil : element
}
print(output) // [1, 8, 10, 12, 19]
let input = [1,2,3,4,8,10,12,19]
func filterConsecutive(array: [Int]) -> [Int] {
guard array.count > 1 else {
return array
}
var result = [Int]()
for i in 0...array.count-2 {
let first = array[i]
let second = array[i+1]
if second != first + 1 {
result.append(second)
}
}
return result
}
let result = filterConsecutive(array: input)

How to mutate an array of integers in-place in swift through filtering

One can filter an array like this in swift:
var numbers = Array(1...1000000)
numbers = numbers.filter( { return $0 % 2 == 0 } )
Is it possible to filter and avoid the copy operation, that occurs when the filtering is done, e.g mutating the original array.
In a similar way to this pseudocode:
numbers.MutablefilterOperation({ return $0 % 2 == 0})
In C++ the equvivalent to what is going on in Swift above would be:
std::vector<int> originalNumbers(1000000);
std::vector<int> newNumbers;
std::copy_if (originalNumbers.begin(), originalNumbers.end(), std::back_inserter(newNumbers), [](int i) { return i % 2 == 0 } );
What I would like to achieve for performance reasons:
std::vector<int> originalNumbers(1000000);
auto pos = std::remove_if(originalNumbers.begin(), originalNumbers.end(), [](int x) { return x % 2 == 0; });
originalNumbers.erase(pos, originalNumbers.end());
This implementation should do the filtering without having to make a temporary copy of the entire array in the process (unless a copy of it is referenced by another variable, see "Copy on Write")
extension Array {
mutating func filterInPlace(isIncluded: (Element) throws -> Bool) rethrows {
var writeIndex = self.startIndex
for readIndex in self.indices {
let element = self[readIndex]
let include = try isIncluded(element)
if include {
if writeIndex != readIndex {
self[writeIndex] = element
}
writeIndex = self.index(after: writeIndex)
}
}
self.removeLast(self.distance(from: writeIndex, to: self.endIndex))
}
}
// example:
var arr = [6,2,6,5,2,5,6,2,2,1,6,7,3]
arr.filterInPlace { $0 % 2 == 1 }
print(arr) // [5, 5, 1, 7, 3]

Resources