PROBLEM
let x = (0..<10).splitEvery( 3 )
XCTAssertEqual( x, [(0...2),(3...5),(6...8),(9)], "implementation broken" )
COMMENTS
I am running into problems calculating number of elements in the Range, etc...
extension Range
{
func splitEvery( nInEach: Int ) -> [Range]
{
let n = self.endIndex - self.startIndex // ERROR - cannot invoke '-' with an argument list of type (T,T)
}
}
The values in a range are of ForwardIndexType, so you can only advance() them,
or compute the distance(), but the subtraction - is not defined. The advance amount has to be of the corresponding
type T.Distance. So this would be a possible implementation:
extension Range {
func splitEvery(nInEach: T.Distance) -> [Range] {
var result = [Range]() // Start with empty array
var from = self.startIndex
while from != self.endIndex {
// Advance position, but not beyond the end index:
let to = advance(from, nInEach, self.endIndex)
result.append(from ..< to)
// Continue with next interval:
from = to
}
return result
}
}
Example:
println( (0 ..< 10).splitEvery(3) )
// Output: [0..<3, 3..<6, 6..<9, 9..<10]
Note however that 0 ..< 10 is not a list (or array) of integers. To split an array into subarrays you could define a similar extension:
extension Array {
func splitEvery(nInEach: Int) -> [[T]] {
var result = [[T]]()
for from in stride(from: 0, to: self.count, by: nInEach) {
let to = advance(from, nInEach, self.count)
result.append(Array(self[from ..< to]))
}
return result
}
}
Example:
println( [1, 1, 2, 3, 5, 8, 13].splitEvery(3) )
// Output: [[1, 1, 2], [3, 5, 8], [13]]
A more general approach could be to split all sliceable objects. But Sliceable
is protocol and protocols cannot be extended. What you can do instead is to
define a function that takes the sliceable object as the first argument:
func splitEvery<S : Sliceable>(seq : S, nInEach : S.Index.Distance) -> [S.SubSlice] {
var result : [S.SubSlice] = []
var from = seq.startIndex
while from != seq.endIndex {
let to = advance(from, nInEach, seq.endIndex)
result.append(seq[from ..< to])
from = to
}
return result
}
(Note that this function is completely unrelated to the (extension) methods
defined above.)
Example:
println( splitEvery("abcdefg", 2) )
// Output: [ab, cd, ef, g]
println( splitEvery([3.1, 4.1, 5.9, 2.6, 5.3], 2) )
// Output: [[3.1, 4.1], [5.9, 2.6], [5.3]]
Ranges are not sliceable, but you could define a separate function that takes a
range argument:
func splitEvery<T>(range : Range<T>, nInEach : T.Distance) -> [Range<T>] {
var result : [Range<T>] = []
var from = range.startIndex
while from != range.endIndex {
let to = advance(from, nInEach, range.endIndex)
result.append(from ..< to)
from = to
}
return result
}
Example:
println( splitEvery(0 ..< 10, 3) )
// Output: [0..<3, 3..<6, 6..<9, 9..<10]
Related
Let's say I have two objects.
obj1 = {
a: 1,
b: 3,
c: 1
}
obj2 = {
a: 3,
b: 1,
c: 3
}
And I would like to add these two. In a way that each key value add them together with the corresponding one. So obj3 = obj1 + obj2 would result in:
obj3 = {
a: 4,
b: 4,
c: 4
}
Is there a simpler way of doing this without manually adding each key value pair like
obj3.a = obj1.a + obj2.a
This is something that could be done very simply through the use of Array.prototype.reduce() if you were able to store these objects as an array:
const myObjects = [
{
a: 1,
b: 3,
c: 1,
},
{
a: 3,
b: 1,
c: 3,
},
];
const output = myObjects.reduce((prev, curr) => ({
a: prev.a + curr.a,
b: prev.b + curr.b,
c: prev.c + curr.c,
}));
This function sum property's object (dynamic property)
function objSumProperty(obj1, obj2) {
const data = {};
Object.keys(obj1).map((k) => (data[k] = obj1[k] + (obj2[k] || 0)));
return data;
}
Use parameters rest (...) to collect all objects to an array. Create an array of all entries ([key, value] pairs) using Array.flatMap() with Object.entries(). Reduce the array of entries to a single object.
This function allows you to combine all keys from 2 or more objects, even if the objects have different keys.
const fn = (...objs) => objs
.flatMap(Object.entries)
.reduce((acc, [key, value]) => ({
...acc,
[key]: (acc[key] ?? 0) + value
}), {})
const obj1 = {"a":1,"b":3,"c":1}
const obj2 = {"a":3,"b":1,"c":3}
console.log(fn(obj1, obj2)) // combining 2 objects
const obj3 = {"a":10,"d":15,"e":20}
console.log(fn(obj1, obj2, obj3)) // combining 3 objects
I started learning Groovy, and understood that parentheses are optional in method calls, so
def list = [0, 1, 2, 3]
list.each ({ item ->
println "Item: $item"
})
is the same as
def list = [0, 1, 2, 3]
list.each { item ->
println "Item: $item"
}
But now found this example
def list = [0, 1, 2, 3]
list.each() { item ->
println "Item: $item"
}
which also works. How is it possible to first call method with empty parameter list, and then specify closure after it?
Things are a little different when closures are involved. There is a special facility for closures that occur as the last parameter (as explained here).
As another illustration, consider:
class Foo {
int bar(s, c) {
return c(s)
}
int abc(c, s) {
return c(s)
}
}
def foo = new Foo()
def s = "fox"
This is a classic style:
assert 3 == foo.bar(s, { it.size() })
Yet this will work for closures as last argument:
assert 3 == foo.bar(s) { it.size() }
This is classic:
assert 3 == foo.abc({ it.size() }, s)
But this won't work
// assert 3 == foo.abc({ it.size() }) s
No doubt the reasoning is that if there is only one parameter, as with List.each(), then the syntax is very elegant:
list.each { item -> println item }
How does one determine the position of an element present in slice?
I need something like the following:
type intSlice []int
func (slice intSlice) pos(value int) int {
for p, v := range slice {
if (v == value) {
return p
}
}
return -1
}
Sorry, there's no generic library function to do this. Go doesn't have a straight forward way of writing a function that can operate on any slice.
Your function works, although it would be a little better if you wrote it using range.
If you happen to have a byte slice, there is bytes.IndexByte.
You can create generic function in idiomatic go way:
func SliceIndex(limit int, predicate func(i int) bool) int {
for i := 0; i < limit; i++ {
if predicate(i) {
return i
}
}
return -1
}
And usage:
xs := []int{2, 4, 6, 8}
ys := []string{"C", "B", "K", "A"}
fmt.Println(
SliceIndex(len(xs), func(i int) bool { return xs[i] == 5 }),
SliceIndex(len(xs), func(i int) bool { return xs[i] == 6 }),
SliceIndex(len(ys), func(i int) bool { return ys[i] == "Z" }),
SliceIndex(len(ys), func(i int) bool { return ys[i] == "A" }))
You could write a function;
func indexOf(element string, data []string) (int) {
for k, v := range data {
if element == v {
return k
}
}
return -1 //not found.
}
This returns the index of a character/string if it matches the element. If its not found, returns a -1.
There is no library function for that. You have to code by your own.
Go supports generics as of version 1.18, which allows you to create a function like yours as follows:
func IndexOf[T comparable](collection []T, el T) int {
for i, x := range collection {
if x == el {
return i
}
}
return -1
}
If you want to be able to call IndexOf on your collection you can alternatively use #mh-cbon's technique from the comments.
You can just iterate of the slice and check if an element matches with your element of choice.
func index(slice []string, item string) int {
for i := range slice {
if slice[i] == item {
return i
}
}
return -1
}
Since Go 1.18 you can also use the experimental generic slices package from https://pkg.go.dev/golang.org/x/exp/slices like this:
package main
import "golang.org/x/exp/slices"
func main() {
s := []int{1,2,3,4,5}
wanted := 3
idx := slices.Index(s, wanted)
fmt.Printf("the index of %v is %v", wanted, idx)
}
It will return -1, if wanted is not in the slice. Test it at the playground.
This is my preferred way, since this might become part of the standard library someday.
Another option is to sort the slice using the sort package, then search for the thing you are looking for:
package main
import (
"sort"
"log"
)
var ints = [...]int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}
func main() {
data := ints
a := sort.IntSlice(data[0:])
sort.Sort(a)
pos := sort.SearchInts(a, -784)
log.Println("Sorted: ", a)
log.Println("Found at index ", pos)
}
prints
2009/11/10 23:00:00 Sorted: [-5467984 -784 0 0 42 59 74 238 905 959 7586 7586 9845]
2009/11/10 23:00:00 Found at index 1
This works for the basic types and you can always implement the sort interface for your own type if you need to work on a slice of other things. See http://golang.org/pkg/sort
Depends on what you are doing though.
I had the same issue few months ago and I solved in two ways:
First method:
func Find(slice interface{}, f func(value interface{}) bool) int {
s := reflect.ValueOf(slice)
if s.Kind() == reflect.Slice {
for index := 0; index < s.Len(); index++ {
if f(s.Index(index).Interface()) {
return index
}
}
}
return -1
}
Use example:
type UserInfo struct {
UserId int
}
func main() {
var (
destinationList []UserInfo
userId int = 123
)
destinationList = append(destinationList, UserInfo {
UserId : 23,
})
destinationList = append(destinationList, UserInfo {
UserId : 12,
})
idx := Find(destinationList, func(value interface{}) bool {
return value.(UserInfo).UserId == userId
})
if idx < 0 {
fmt.Println("not found")
} else {
fmt.Println(idx)
}
}
Second method with less computational cost:
func Search(length int, f func(index int) bool) int {
for index := 0; index < length; index++ {
if f(index) {
return index
}
}
return -1
}
Use example:
type UserInfo struct {
UserId int
}
func main() {
var (
destinationList []UserInfo
userId int = 123
)
destinationList = append(destinationList, UserInfo {
UserId : 23,
})
destinationList = append(destinationList, UserInfo {
UserId : 123,
})
idx := Search(len(destinationList), func(index int) bool {
return destinationList[index].UserId == userId
})
if idx < 0 {
fmt.Println("not found")
} else {
fmt.Println(idx)
}
}
Another option if your slice is sorted is to use SearchInts(a []int, x int) int which returns the element index if it's found or the index the element should be inserted at in case it is not present.
s := []int{3,2,1}
sort.Ints(s)
fmt.Println(sort.SearchInts(s, 1)) // 0
fmt.Println(sort.SearchInts(s, 4)) // 3
https://play.golang.org/p/OZhX_ymXstF
I have a collection of objects that I want to break up into a collection of collections, where each sequential group of 3 elements is in one collection.
For example, if I have
def l = [1,4,2,4,5,9]
I want to turn this into:
def r = [[1,4,2], [4,5,9]]
I'm doing it now by iterating over the collection and breaking it up.. but I then need to pass those 'groups' into a parallelized function that processes them.. It would be nice to eliminate this O(n) pre-processing work and just say something like
l.slice(3).collectParallel { subC -> process(subC) }
I've found the step method on the Range class, but it looks like that only acts on the indices. Any clever ideas?
Update:
I don't think this is a duplicate of the referenced link, although it's very close. As suggested below, it's more of the iterator-type thing I'm looking for.. the sub-collections will then be passed into a GPars collectParallel. Ideally I wouldn't need to allocate an entire new collection.
Check out groovy 1.8.6. There is a new collate method on List.
def list = [1, 2, 3, 4]
assert list.collate(4) == [[1, 2, 3, 4]] // gets you everything
assert list.collate(2) == [[1, 2], [3, 4]] //splits evenly
assert list.collate(3) == [[1, 2, 3], [4]] // won't split evenly, remainder in last list.
Take a look at the Groovy List documentation for more info because there are a couple of other params that give you some other options, including dropping the remainder.
As far as your parallel processing goes, you can cruise through the lists with gpars.
def list = [1, 2, 3, 4, 5]
GParsPool.withPool {
list.collate(2).eachParallel {
println it
}
}
If I understand you correctly, you're currently copying the elements from the original collection into the sub-collections. For more suggestions along those lines, checkout the answers to the following question: Split collection into sub collections in Groovy
It sounds like what you're instead looking for is a way for the sub-collections to effectively be a view into the original collection. If that's the case, check out the List.subList() method. You could either loop over the indices from 0 to size() in increments of 3 (or whatever slice size you choose) or you could get fancier and build an Iterable/List which would hide the details from the caller. Here's an implementation of the latter, inspired by Ted's answer.
class Slicer implements Iterator {
private List backingList
private int sliceSize
private int index
Slicer(List backingList, int sliceSize) {
this.backingList = backingList
this.sliceSize = sliceSize
}
Object next() {
if (!hasNext()) {
throw new NoSuchElementException()
}
def ret
if (index + sliceSize <= backingList.size()) {
ret = backingList.subList(index, index+sliceSize)
} else if (hasNext()) {
ret = backingList.subList(index, backingList.size())
}
index += sliceSize
return ret
}
boolean hasNext() {
return index < backingList.size()
}
void remove() {
throw new UnsupportedOperationException() //I'm lazy ;)
}
}
I like both solutions but here is a slightly improved version of the first solution that I like very much:
class Slicer implements Iterator {
private List backingList
private int sliceSize
private int index
Slicer(List backingList, int sliceSize) {
this.backingList = backingList;
int ss = sliceSize;
// negitive sliceSize = -N means, split the list into N equal (or near equal) pieces
if( sliceSize < 0) {
ss = -sliceSize;
ss = (int)((backingList.size()+ss-1)/ss);
}
this.sliceSize = ss
}
Object next() {
if (!hasNext()) {
throw new NoSuchElementException()
}
def ret = backingList.subList(index, Math.min(index+sliceSize , backingList.size()) );
index += sliceSize
return ret
}
boolean hasNext() {
return index < backingList.size() - 1
}
void remove() {
throw new UnsupportedOperationException() //I'm lazy ;)
}
List asList() {
this.collect { new ArrayList(it) }
}
List flatten() {
backingList.asImmutable()
}
}
// ======== TESTS
def a = [1,2,3,4,5,6,7,8];
assert [1,2,3,4,5,6,7,8] == a;
assert [[1, 2], [3, 4], [5, 6], [7, 8]] == new Slicer(a,2).asList();
assert [[1,2,3], [4,5,6], [7,8]] == (new Slicer(a,3)).collect { it } // alternative to asList but inner items are subList
assert [3, 2, 1, 6, 5, 4, 8, 7] == ((new Slicer(a,3)).collect { it.reverse() } ).flatten()
// show flatten iterator
//new Slicer(a,2).flattenEach { print it }
//println ""
// negetive slice into N pieces, in this example we split it into 2 pieces
assert [[1, 2, 3, 4], [5, 6, 7, 8]] == new Slicer(a,-2).collect { it as List } // same asList
assert [[1, 2, 3], [4, 5, 6], [7, 8]] == new Slicer(a,-3).asList()
//assert a == (new Slicer(a,3)).flattenCollect { it }
assert [9..10, 19..20, 29..30] == ( (new Slicer(1..30,2)).findAll { slice -> !(slice[1] % 10) } )
assert [[9, 10], [19, 20], [29, 30]] == ( (new Slicer(1..30,2)).findAll { slice -> !(slice[1] % 10) }.collect { it.flatten() } )
println( (new Slicer(1..30,2)).findAll { slice -> !(slice[1] % 10) } )
println( (new Slicer(1..30,2)).findAll { slice -> !(slice[1] % 10) }.collect { it.flatten() } )
There isn't anything built in to do exactly what you want, but if we #Delegate calls to the native lists's iterator, we can write our own class that works just like an Iterator that returns the chunks you're looking for:
class Slicer {
protected Integer sliceSize
#Delegate Iterator iterator
Slicer(objectWithIterator, Integer sliceSize) {
this.iterator = objectWithIterator.iterator()
this.sliceSize = sliceSize
}
Object next() {
List currentSlice = []
while(hasNext() && currentSlice.size() < sliceSize) {
currentSlice << this.iterator.next()
}
return currentSlice
}
}
assert [[1,4,2], [4,5,9]] == new Slicer([1,4,2,4,5,9], 3).collect { it }
Because it has all of the methods that a normal Iterator does, you get the groovy syntactic sugar methods for free with lazy evaluation on anything that has an iterator() method, like a range:
assert [5,6] == new Slicer(1..100, 2).find { slice -> slice.first() == 5 }
assert [[9, 10], [19, 20], [29, 30]] == new Slicer(1..30, 2).findAll { slice -> !(slice[1] % 10) }
I've tried and surprised how could not I do with ExtJS. Let me explain with a code block.
In jQuery
console.clear();
var a = {
b: 5,
c: 4,
o: {
l: 2,
p: 2
}
}
var b = {
k: 4,
l: 3,
c: 5,
o: {
m: 2,
l: 1
}
}
var ex = $.extend(true, a, b);
console.dir(ex)
Here is the output
ex = {
a: {
q: 2
},
b: 5,
c: 5,
o: {
l: 1,
p: 2,
m: 2
}
}
Ext apply, applyIf, copyTo does not worked like this. How can I produce the output in ExtJS?
Thanks in advance.
For a recent project, we adapted this sample code to produce the following method:
Ext.deepCopy = function(p, c) {
c = c || (p.constructor === Array ? [] : {});
for (var i in p) {
if (typeof p[i] === 'object' && p[i] !== null) {
c[i] = p[i].constructor === Array ? [] : {};
Ext.deepCopy(p[i], c[i]);
} else {
c[i] = p[i];
}
}
return c;
};
Deep copying isn't supported in Ext. There are Ext.apply and Ext.applyIf but they both only work on the first level of a hash map and will override instead of merge any embedded arrays or hashes.
In fact the docs explicitly state that Ext.apply is meant to work on config objects, not that it matters but it's just to illustrate that it's not meant to be used as a merge utility function although it basically could if you only want to merge the first level/depth.
Use the Ext.Object.merge() method, that does exactly what you're looking for.