Check if SOME array values are equal - arrays

I'm looking for a way to check if some values of an array are equal, here is an example :
[1, 2, 3, 4] //False
[1, 1, 2, 3] //True
['a', 'a', 'a', 'a', ] // True
I already found this method, that returns 'true' if EVERY array values are equal but it's not what I want :
console.log([1,1,1,1].every( (val, i, arr) => val === arr[0] ))
Thanks

If the collection obtained by keeping only the distinct elements is smaller than the original collection, then there were duplicate elements:
val seq = Seq(1, 1, 2, 3)
seq.distinct.size < seq.size
//=> true
This typically runs in O(n) time and O(n) space. However, you should be able to also make it short-circuiting so that it aborts as soon as it finds a duplicate element:
require 'set'
ary = [1, 2, 3, 1]
!ary.each_with_object(Set[]) {|el, set| break if set.include?(el); set << el }
#=> true

Related

Sorting array items by frequency value

is there a good way or algorithm to sort an array by the value of a frequency in each item? Let's say I have this array:
[3, 3, 3, 5, 6, 12, 5, 5, 6]. I want the output to be [3, 5, 6, 12]. I was thinking about something like insertionsort but I belive that there could be an easier way.
Well, you definetly need the count for each element, which is O(n). Then you can make a unique list from it (let's say it has m elements), and sort it according to the frequency with any sorting algo, you like. It will be O(n+mlog(m)).
For example in python:
from collections import Counter
myList = ['a', 'b', 'b', 'a', 'b', 'c']
myCounter = Counter(myList)
myUniqueList = list(myCounter)
sorted(myUniqueList, key=lambda e: myCounter[e])
Editted according to Paddy3118 's comment
First you count them
std::unordered_map<int, int> dict;
for(auto &val : array)
dict[val]++; // O(N)
Then you sort them
std::vector vec(dict.begin(), dict.end());
std::sort(vec.begin(), vec.end(), [](auto a, auto b) { return a.second > b.second }); // O(M lg M), requires C++14 to use auto

Swift : Performing operations on certain elements of an array

So, something is bugging me with the syntax in Swift for performing operations on Arrays of Ints.
What I wanna do is this : I have an array of Ints which is outputted from a function, its size (count) varies between say 2 and 6 for now, depending on buttons I press in my app.
For each array that is outputted and that contain n ints, I want to create n arrays on which to perform an other action later on.
These "sub" arrays are supposed to be calculated this way :
newArray1's values should be array's values - the value of the first index of newArray1
newArray2's values should be array's values - the value of the second index of newArray2
etc... (I'll automate the number of newArrays according to the array.count)
An other condition applying for those new arrays is that if at a given index the value is negative, I add 12 (so it'll occur for newArray2 at index 1, for newArray3 at indexes 1 & 2, etc... as long as those newArrays are created).
Here's how I wanted to perform that (I created this with dummy arbitrary array in the playground for the sake of testing before inserting the correct stuff in my app code) :
var array : [Int] = [2,4,6,8,9]
var newArray2 = [Int]()
var increment2 = Int()
increment2 = array[1]
newArray2 = array.map {$0 - increment2}
for i in 0..<newArray2.count {
if array[i] < 0 {
newArray2[i] = array[i] + 12
} else {
newArray2[i] = array[i]
}
}
print(array)
print(newArray2)
So of course it doesn't work because I can't seem to figure how to correctly perform operations on Arrays...
Intuitively it seems in my first if statement I'm comparing not the element at index i but i itself, not sure how to reformat that though...
Any help is most welcome, thanks in advance ! :)
[EDIT: I just edited the names of newArray1 to newArray2, same for increments, so that I have negative values and it matches the index value of 1 which is the second element of my main array]
You seem to mean this:
let arr = [2,4,6,8,9]
var results = [[Int]]()
for i in arr.indices {
results.append(arr.map {
var diff = $0-arr[i]
if diff < 0 { diff += 12 }
return diff
})
}
// results is now:
// [[0, 2, 4, 6, 7],
// [10, 0, 2, 4, 5],
// [8, 10, 0, 2, 3],
// [6, 8, 10, 0, 1],
// [5, 7, 9, 11, 0]]

Reduce array to tuple of first and last element?

I have an array that I would like to first sort, then return the first and last element of the sorted array. I thought I can use reduce, but what if I don't have an initial value?
Here is the array I'm trying to work with:
let myNumbers = [4, 9, 6, 2, 3]
How can map this to the first and last of the sorted array to this?:
(2, 9)
Method 1: min()/max()
This is the easiest way:
let input = [4, 9, 6, 2, 3]
let output = (input.min(), input.max())
print(output) //(Optional(2), Optional(9))
If you're certain that the array isn't empty, you can safely force unwrap the optionals:
let input = [4, 9, 6, 2, 3]
let output = (input.min()!, input.max()!) // (2, 9)
This is approach does 2 iterations over the array. It's O(N). Unless a sorted list is required elsewhere, sorting then taking the first/last would be worse, as it would be O(N * log_2(N)).
Method 2: reduce()
If you insist on using reduce, you can do it like this:
let input = [4, 9, 6, 2, 3]
let output = input.reduce((min: Int.max, max: Int.min)){
(min($0.min, $1), max($0.max , $1))
} //(2, 9)
Each reduce iteration sets the accumulator to the new min (the smaller of the old min and current element), and the new max (the larger of the old max and the current).
The initial values of the accumulator are set such that:
Any element in the array compares as smaller than the accumulator's min
Any element in the array compares as larger than the accumulator's max
You don't need an initialValue for reduce, it's optional.
var foo = [1, 40, 20, -20, 50];
var reducer = function(prev, curr, i, arr){return [prev[0] <= curr ? prev[0] : curr, prev[1] >= curr ? prev[1] : curr]};
var baz = foo.reduce(reducer); // [-20, 50]
Or maybe like this:
var foo = [1, 40, 20, -20, 50];
var reducer = function(prev, curr, i, arr){return {min: prev.min <= curr ? prev.min : curr, max: prev.max >= curr ? prev.max : curr}};
var baz = foo.reduce(reducer); // {min: -20, max: 50}
Edit: Just noticed this is for swift and not javascript, whoops lol. I must have been surfing the wrong SO category. I think the principle would be the same in swift except you probably do need to provide some kind of initial value.

Ruby Arrays: Why is the value I print correct, but the value I push incorrect?

I'm attempting a kata that has had me stumped for over an hour. Essentially, I'm attempting to find the smallest combination of numbers in an array by only moving one element at a time.
The issue i'm having is when I print the array (p arr) I get the result in the terminal I'm expecting. So i presumed I can push that value to arr_collection (which is just a collection of array combinations). When I push the value, and return arr_collection I get a result of duplicate values, not consistent with what I printed on the line before the push.
I hope this makes sense, but the return value of smallest([2,6,1,2,3,5]) should be a 2d array consisting of various array values, including [1,2,6,2,3,5] which is the smallest combination of them all (given the constraint of only moving 1 element at a time).
I'd like to know why all the values returned from this method are duplicated, when instead they should be a mixed combination of numbers.
def smallest(arr)
arr_collection = []
arr.each_with_index do |num, index|
unless index == 0
arr.unshift(num)
arr.delete_at(index+1)
#p arr #when I print this, I get the result I want
arr_collection << arr #when I push this into an array, and return that array below, I just get duplicate values
arr.insert(index+1, num)
arr.shift
end
end
return arr_collection #why do I get a return value inconsistent with the values I printed in the each block
end
print smallest([2,6,1,2,3,5]) #[1,2,6,2,3,5]**
You are mutating the same array you're adding to the collection after you add it, here:
arr_collection << arr
arr.insert(index+1, num) # mutating the same arr that is in the collection
arr.shift
And then when you go through another loop iteration, the lines above:
arr.unshift(num)
arr.delete_at(index+1)
...are mutating that same arr again.
You need to add a copy of arr to the array so that subsequent mutations won't affect it:
def smallest(arr)
arr_collection = []
arr.each_with_index do |num, index|
next if index == 0
arr.unshift(num)
arr.delete_at(index+1)
arr_collection << arr.dup # add copy of arr to the collection
arr.insert(index+1, num) # no longer mutating the same arr that is in collection
arr.shift
end
arr_collection
end
smallest [2,6,1,2,3,5]
# => [[6, 2, 1, 2, 3, 5], [1, 2, 6, 2, 3, 5], [2, 2, 6, 1, 3, 5], [3, 2, 6, 1, 2, 5], [5, 2, 6, 1, 2, 3]]

Splitting an Array into Sub-Arrays in Swift [duplicate]

This question already has answers here:
In Swift, an efficient function that separates an array into 2 arrays based on a predicate
(7 answers)
Closed 6 months ago.
Problem
Given an array of values how can I split it into sub-arrays made of elements that are equal?
Example
Given this array
let numbers = [1, 1, 1, 3, 3, 4]
I want this output
[[1,1,1], [3, 3], [4]]
What I am NOT looking for
A possible way of solving this would be creating some sort of index to indicate the occurrences of each element like this.
let indexes = [1:3, 3:2, 4:1]
And finally use the index to rebuild the output array.
let subsequences = indexes.sort { $0.0.0 < $0.1.0 }.reduce([Int]()) { (res, elm) -> [Int] in
return res + [Int](count: elm.1, repeatedValue: elm.0)
}
However with this solution I am losing the original values. Of course in this case it's not a big problem (an Int value is still and Inteven if recreated) but I would like to apply this solution to more complex data structures like this
struct Starship: Equatable {
let name: String
let warpSpeed: Int
}
func ==(left:Starship, right:Starship) -> Bool {
return left.warpSpeed == right.warpSpeed
}
Final considerations
The function I am looking for would be some kind of reverse of flatten(), infact
let subsequences: [[Int]] = [[1,1,1], [3, 3], [4]]
print(Array(subsequences.flatten())) // [1, 1, 1, 3, 3, 4]
I hope I made myself clear, let me know should you need further details.
// extract unique numbers using a set, then
// map sub-arrays of the original arrays with a filter on each distinct number
let numbers = [1, 1, 1, 3, 3, 4]
let numberGroups = Set(numbers).map{ value in return numbers.filter{$0==value} }
print(numberGroups)
[EDIT] changed to use Set Initializer as suggested by Hamish
[EDIT2] Swift 4 added an initializer to Dictionary that will do this more efficiently:
let numberGroups = Array(Dictionary(grouping:numbers){$0}.values)
For a list of objects to be grouped by one of their properties:
let objectGroups = Array(Dictionary(grouping:objects){$0.property}.values)
If you could use CocoaPods/Carthage/Swift Package Manager/etc. you could use packages like oisdk/SwiftSequence which provides the group() method:
numbers.lazy.group()
// should return a sequence that generates [1, 1, 1], [3, 3], [4].
or UsrNameu1/TraverSwift which provides groupBy:
groupBy(SequenceOf(numbers), ==)
If you don't want to add external dependencies, you could always write an algorithm like:
func group<S: SequenceType where S.Generator.Element: Equatable>(seq: S) -> [[S.Generator.Element]] {
var result: [[S.Generator.Element]] = []
var current: [S.Generator.Element] = []
for element in seq {
if current.isEmpty || element == current[0] {
current.append(element)
} else {
result.append(current)
current = [element]
}
}
result.append(current)
return result
}
group(numbers)
// returns [[1, 1, 1], [3, 3], [4]].
Let's assume that you have an unsorted array of items. You will need to sort the initial array then you will have something like this:
[1, 1, 1, 3, 3, 4]
After that you will initialize two arrays: one for storing arrays and another one to use it as a current array.
Loop through the initial array and:
if the current value isn't different from the last one, push it to the current array
otherwise push the current array to the first one then empty the current array.
Hope it helps!
Worth mentioning, using Swift Algorithms this is now a one-liner:
import Algorithms
let numbers = [1, 1, 1, 3, 3, 4]
let chunks: [[Int]] = numbers.chunked(by: ==).map { .init($0) }
print(chunks) // [[1, 1, 1], [3, 3], [4]]

Resources