I have a List[<DataType>] as input. I want to check if the list contains all the same values(not datatype).
Is there inbuilt method or intuitive way in Scala to do this instead of iterating over list and checking.
This will terminate on the first non-equals element. The element type has to support a comparator like == or !=.
lst.forall(_ == lst.head) // true if empty or all the same
lst.exists(_ != lst.head) // false if empty or all the same
One (inefficient but elegant) way is
List(1, 2, 2, 1, 1).distinct.length == 1 // returns false
List(1, 1, 1, 1, 1).distinct.length == 1 // returns true
List().distinct.length == 1 // empty list returns false
Note that they must be of the same type
List(4, 4.0, "4").distinct.length == 1 // returns false
I just had to do this for an unrelated problem, so to improve on the above ever so slightly: lst.tail.forall(_ == lst.head). This avoids checking that the head of the list equals itself, which you already know is true.
Related
I am going through the List methods in Scala.
val mylist = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 3, 10)
I am quite confused by hasDefiniteSize and knownSize.
For List, hasDefiniteSize returns true and knownSize returns -1.
What is the exact theory behind these methods?
This method is defined by a superclass of List which is common with possibly endless collections (like Streams, LazyLists and Iterators).
For more details, I believe the documentation puts it best.
Here is the one for hasDefiniteSize in version 2.13.1:
Tests whether this collection is known to have a finite size. All
strict collections are known to have finite size. For a non-strict
collection such as Stream, the predicate returns true if all elements
have been computed. It returns false if the stream is not yet
evaluated to the end. Non-empty Iterators usually return false even if
they were created from a collection with a known finite size.
Note: many collection methods will not work on collections of infinite
sizes. The typical failure mode is an infinite loop. These methods
always attempt a traversal without checking first that hasDefiniteSize
returns true. However, checking hasDefiniteSize can provide an
assurance that size is well-defined and non-termination is not a
concern.
Note that hasDefiniteSize is deprecated with the following message:
(Since version 2.13.0) Check .knownSize instead of .hasDefiniteSize
for more actionable information (see scaladoc for details)
The documentation for knownSize further states:
The number of elements in this collection, if it can be cheaply
computed, -1 otherwise. Cheaply usually means: Not requiring a
collection traversal.
List is an implementation of a linked list, which is why List(1, 2, 3).hasDefiniteSize returns true (the collection is not boundless) but List(1, 2, 3).knownSize returns -1 (computing the collection size requires traversing the whole list).
Some collections know their size
Vector(1,2,3).knownSize // 3
and some do not
List(1,2,3).knownSize // -1
If a collection knows its size then some operations can be optimised, for example, consider how Iterable#sizeCompare uses knownSize to possibly return early
def sizeCompare(that: Iterable[_]): Int = {
val thatKnownSize = that.knownSize
if (thatKnownSize >= 0) this sizeCompare thatKnownSize
else {
val thisKnownSize = this.knownSize
if (thisKnownSize >= 0) {
val res = that sizeCompare thisKnownSize
// can't just invert the result, because `-Int.MinValue == Int.MinValue`
if (res == Int.MinValue) 1 else -res
} else {
val thisIt = this.iterator
val thatIt = that.iterator
while (thisIt.hasNext && thatIt.hasNext) {
thisIt.next()
thatIt.next()
}
java.lang.Boolean.compare(thisIt.hasNext, thatIt.hasNext)
}
}
}
See related question Difference between size and sizeIs
I want to choose index from list, so the element[index] complies my condition.
MyList[index].num==0
I tried the code bellow:
gen DescIdx2Choose keeping {
it < MyList.size();
MyList[it].num==0;//I tried a few way of read_only
};
How can I do it without using all_indices?
Thanks
Since you generating DescIdx2Choose then MyList will be input to the problem.
Therefore,
If seeking for the first index (if exists) then using random generation isn't required. Use the procedural code "first_index" as user3467290 suggested which is much more efficient:
var fidx := MyList.first_index(.num == 0);
if ( fidx != UNDEF ) {
DescIdx2Choose = fidx;
} else {
// error handling
};
If there are multiple indices and it is required to choose a random one, the most efficient way would be using "all_indices" as Thorsten suggested:
gen DescIdx2Choose keeping {
it in read_only( MyList.all_indices(.num == 0) );
};
The reason is the random generator doesn't need to read all possible values of "MyList.num" only a shorter list of valid indices.
This should do it, but MyList must fulfill the condition otherwise you get a contradiction. Pseudo-method first_index() is not bi-directional which is what we need here.
gen DescIdx2Choose keeping {
MyList.first_index(.num == 0) == it;
};
Maybe i missed something in the question, but If you always want the index of the first element that its num == 0, then why use constraints? can assign DescIdx2Choose == MyList.first_index(.num == 0).
To ensure that there is at least one such element, can constrain MyList.has(.num == 0).
Do you have additional constraints on DescIdx2Choose ?
I am trying to create a function that takes an array of Int, and returns a new array of all of the even numbers in the original array.
I have been fumbling around with this code (I am a very new beginner)
let numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var newArray: [Int] = []
func newInt(newEven: Int, newArray: [Int]) -> Int {
for newEven in numberArray{
var index = 0
index += 1
if newEven % 2 == 0 {
newArray.insert(newEven, at:[index])
}
return newEven
}
}
print(newArray)
This is a good start! Here are some pointers:
1. Formatting
The formatting needs some work. Generally, every new scope ({ ... }) should introduce a new layer of indentation, like so:
let numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var newArray: [Int] = []
func newInt(newEven: Int, newArray: [Int]) -> Int {
for newEven in numberArray{
var index = 0
index += 1
if newEven % 2 == 0 {
newArray.insert(newEven, at:[index])
}
return newEven
}
}
print(newArray)
Now we can make some observations:
1. index is scoped to the for loop body, and will always have the same value of 0, and then 1 after the next line.
2. The return statement is within the for loop body, and unconditional. This function will always return the value of the first element of numberArray
3. The return type of this function is Int. But in your question, you state that you want this to return an array of all of the even numbers. So your return type will have to be Array<Int> (a.k.a. [Int]), not just Int.
2. Compilation issues
This function has several errors that will prevent compilation:
The return statement is within a loop body. If numberArray is empty, and the for loop body is never entered, then you don't hit the return statement. Once control reaches the end of the function, what value should be returned? It's not defined, so that's an error. In Swift, all code paths through a function must return a value. (with the exception of Void functions, which implicitly return nothing at the end)
You're trying to call Array.insert(_:at:) with a second argument of [index], which is an array literal of type Array<Int>. It should just be index.
3. Logical issues
Your function introduces a parameter called newArray, which shadows the global variable newArray on the line before it. The global variable isn't necessary, and you should delete it.
Your function operates over numberArray, but doesn't explicitly take it as input via a parameter. Rather than hardcoding a reference to a global variable like numberArray, you should use a parameter.
The parameter newEven is unused, and is shadowed by the local variable of the for loop
Your function name newInt(newEven:newArray:) doesn't describe what the function does. Consider a function signature like func allEvens(in input: [Int]) -> [Int]
You never actually call this function. You declare it, but never told the program to run it.
You don't need to use Array.insert(_:at:). You can simply use Array.append, which will automatically append elements to the end of the array.
4. Recommendations
Fix the method signature. You want the function to take some numbers, and output only the even numbers. Model that in code: func allEvens(in input: [Int]) -> [Int]
Create a new empty array locally (within the function), into which the even numbers will be stored. As you loop over the input array, check every number if it's even, and if so, append it to the evens array.
Return the evens array.
let numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var newArray = numberArray.filter({$0 % 2 == 0})
This should return a new array with even numbers.
As LeoDabus mentioned in his comment, the functionality you're seeking is already contained within Swift's Standard Library, so it's not really necessary to write a dedicated function to accomplish that task. Here's how you would do it:
let numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let newArray = numberArray.filter { $0.isMultiple(of: 2) }
print(newArray) // [2, 4, 6, 8, 10]
In this, you're using the filter whether $0 (where $0 is an element in your array) is a multiple of the number you specified in the parameter, in this case, 2.
As you see in the documentation, isMultiple(of:) returns a Bool (true or false). This is the signature:
func isMultiple(of other: Self) -> Bool
I would recommend having a peek at this post covering the topics of map, filter, and reduce. These are useful things to know when starting out in Swift.
Additionally, I've found Dash to be extremely helpful in navigating documetation for Swift.
Update
I should have read your question more thoroughly, as I missed the part where you've gotta do it with a loop. Swift has a cool method called forEach, which I'm a huge fan of. Using that methodology, it would look something like this:
func filter(array: [Int], forMultiplesOf multiple: Int) -> [Int] {
// Create a landing spot for whatever is a multiple...it starts as empty
var newArray: [Int] = []
// This is not the most compact way, but it satisfies the loop constraint
array.forEach { number in
if number % multiple == 0 {
newArray.append(number)
}
}
// Once you're done with the loop, then return the new array you declared at the beginning
return newArray
}
And you'd call it like so:
let newArrayUsingFunction = filter(array: numberArray, forMultiplesOf: 2)
What you're doing here is passing in 2 parameters to the function (array & multiple) to return an array of Ints. See comments in code for what's going on
I am trying to build a test case that checks if two streams are the same. Zip can be used to check the value elements are the same, but it doesn't help if one stream is the wrong length. Any ideas on how to approach this?
There's an operator for that: sequenceEqual.
Returns
(Observable): An observable sequence that contains a single element which indicates whether both sequences are of equal length and their corresponding elements are equal according to the specified equality comparer.
Here's a simple example showing the length equality check.
var log = console.log.bind(console);
Rx.Observable.of(1, 2, 3)
.sequenceEqual(Rx.Observable.of(1, 2, 3))
.subscribe(log); // logs true
Rx.Observable.of(1, 2, 3)
.sequenceEqual(Rx.Observable.of(1, 2))
.subscribe(log); // logs false
I have an integer array of length 2000 elements. For ex
x = [2, 4, 5, 6, 5,6,7,5......];
Now in this array i need to find an element which occurs repeatedly. For ex I need to know how many times a number '5' has been occurred. In the above example it is three times.
Is there any way to search an matching element and returns the count in matlab?
Do you know the number in advance?
If so, to work out how many times it appears in x you could do:
sum(x==5)
The x==5 creates a vector of [FALSE FALSE TRUE FALSE TRUE FALSE FALSE TRUE ...], being TRUE whenever x is 5.
The sum then adds up that vector, where FALSE maps to 0 and TRUE to 1.
A quick way get the count is
sum(x == 5)
If you need the indicies of the matching elements:
find(x == 5)
Notice, the count is also length(find(x == 5)).
Standard caveats apply toward the use of == and floating point numbers.