Swift - pruning elements from an Array, converting integer strings to integers - arrays

I have an array that contains numbers and empty strings, like ["", "2", "4", "", "", "1", "2", ""]. I would like to pare this down to a list of numbers, like [2,4,1,2].
My first effort split this into two steps, first strip out the empty strings, then do the string-to-integer conversion. However, my code for step one isn't working as desired.
for (index,value) in tempArray.enumerate(){
if value == "" {
tempArray.removeAtIndex(index)
}
}
This fails, I believe because it is using the index values from the original, complete array, though after the first deletion they are not longer accurate.
What would be a better way to accomplish my goal, and what is the best way to convert the resulting array of integer strings to an array of integers?

var str = ["", "2", "4", "", "", "1", "2", ""]
let filtered = str.filter {$0 != "" }
let intArr = filtered.map {($0 as NSString).integerValue}

With Swift 2 we can take advantage of flatMap and Int():
let stringsArray = ["", "2", "4", "", "", "1", "2", ""]
let intsArray = stringsArray.flatMap { Int($0) }
print(intsArray) // [2, 4, 1, 2]
Explanation: Int() returns nil if the string does not contain an integer, and flatMap ignores nils and unwraps the optional Ints returned by Int().

Related

Swift compare arrays, anyone has an idea how to solve it?

Could someone tell me how I can solve this problem? I have two arrays in array 1 change values, array 2 has to synchronize with the first one, but without losing the value positions. I have tried with difference(from:) but it reorders the values of array 2. Here as it should be, thank you very much for your help.
let array1 = ["01", "06", "17", "22", "33", "45", "04"]
var array2 = ["04", "17", "22", "10", "01", "34"]
//
...
// Result
var array2 = ["04", "17", "22", "01", "06", "33", "45"]
The order of the values in array 2 must remain the same, delete those missing from array 1 and add those missing from array 1 to the end of array 2.
Naive solution:
Copy array1 to a temporary var temp
Loop through the indexes of temp in reverse order. If a value from temp exists in array2, remove it.
Append temp to array2.
That would have poor (roughly O(n^2), or rather O(array1.count*array2.count)) time performance for large arrays, since the array contains() function is O(n). You could speed it up by using a set to track items in array2.
This is the best solution I can get 😉
let array1 = ["01", "06", "17", "22", "33", "45", "04"]
var array2 = ["04", "17", "22", "10", "01", "34"]
let remove = (array2.filter{!array1.contains($0)})
let append = (array1.filter{!array2.contains($0)})
for i in remove {
array2 = array2.filter {$0 != i}
}
array2.append(contentsOf: append)
print("array2:\(array2)")
// array2:["04", "17", "22", "01", "06", "33", "45"]

Replace array in range

I have an array of strings ["", "", "", "1"]
And I want an arrays with all empty strings replaced with zeros - ["0", "0", "0", "1"]
Is there a built-in operator, function or method to help me do this without having to re-invent the wheel?
If your transformation needs strings as result, the comment from TusharSharma provides a solution that answers exactly your question (I'll not repeat it, because I hope he'll enter it as an answer).
However, looking at your example, it seems that you deal with numeric strings. For the records, I'd like to suggest then to simply consider to produce an array of integers.
let s = ["", "", "", "1"]
let r = s.map{Int($0) ?? 0}
If the numbers are doubles:
let r2 = s.map{String(Double($0) ?? 0.0)}
Using the numerics allows you to easily use more advanced build-in formatting:
let r3 = s.map{String(format: "%.2f", Double($0) ?? 0.0)}
or even use some custom number formatter able to use the locales (more here)

How do I split a string with two different delimiters in Ruby and convert it to two arrays?

I have a string
"Param 1: 1, Some text: 2, Example3: 3, Example4: 4"
and I'd like to convert it into an arrays:
["Param 1","Some text","Example3","Example4"]
[1,2,3,4]
How?
Here's a one liner that uses Multiple Assignment to create 2 new named arrays:
a1, a2 = str.split(", ").map{|x| x.split(": ")}.transpose
a1 #=> ["Param 1", "Some text", "Example3", "Example4"]
a2 #=> ["1", "2", "3", "4"]
Although most of this solution has already been mentioned in one form or another in previous suggestions, I prefer this combined approach over others mentioned for a few reasons:
It doesn't utilize regex which makes it execute quicker than some of the other suggestions. Actually, after running a few quick benchmarks, it looks like it actually executes faster than the other non-regex solution listed so far as well.
It simultaneously creates 2 unique and individually named arrays to work with (as opposed to just creating an array with 2 sub arrays).
It carries out the whole operation with one line.
There are plenty of ways to do it in Ruby.
You can first split by pairs' delimiter (comma) and then use map to split further by key/pair delimiter (colon):
pairs = s.split(/,\s*/).map { |s| s.split(/:\s*/) }
keys = pairs.map(&:first)
values = pairs.map(&:last)
(here and below s is your original string)
You can use scan to match keys/values in a single call (disclaimer: it does NOT mean this is more efficient - regexps aren't magic)
pairs = s.scan(/(?<key>[^:]+):\s*(?<value>[^,]+)[,\s]*/)
keys = pairs.map(&:first)
values = pairs.map(&:last)
(named captures aren't necessary here - with scan they don't give any benefits - but I put them to make regexp arguably a bit more readable)
You can split by all delimiters and then use Enumerable#partition to separate keys from values, smth. like:
keys, values = s.split(/:\s*|,\s*/).partition.with_index { |_, i| i.even? }
etc...
Input
a = "Param 1: 1, Some text: 2, Example3: 3, Example4: 4"
Code
obj= a.split(',').map { |x| x.split(':') }
p obj.map(&:first).map(&:strip)
p obj.map(&:last)
Result
["Param 1", "Some text", "Example3", "Example4"]
[" 1", " 2", " 3", " 4"]
You can use String#split with a regular expression, then pair the returned values and transpose:
str = "Param 1: 1, Some text: 2, Example3: 3, Example4: 4"
str.split(/[:,] +/).each_slice(2).to_a.transpose
#=> [["Param 1", "Some text", "Example3", "Example4"],
# ["1", "2", "3", "4"]]
The steps are as follows.
a = str.split(/[:,] +/)
#=> ["Param 1", "1", "Some text", "2", "Example3", "3", "Example4", "4"]
The regular expression reads, "match a colon or comma followed by one or more spaces".
enum = a.each_slice(2)
#=> #<Enumerator: ["Param 1", "1", "Some text", "2", "Example3",
# "3", "Example4", "4"]:each_slice(2)>
b = enum.to_a
#=> [["Param 1", "1"], ["Some text", "2"], ["Example3", "3"],
# ["Example4", "4"]]
b.transpose
#=> [["Param 1", "Some text", "Example3", "Example4"],
# ["1", "2", "3", "4"]]
Here is a second way to perform the calculation that I present without explanation, except to say that it uses the form of String#gsub that takes one argument and no block, returning an enumerator that can be chained to Enumerator#with_object. This form of gsub, unlike the others, does not perform character substitutions (and therefore may be considered misnamed). Rather, the enumerator generates and returns matches of its argument, here a regular expression.
str.gsub(/[a-z][a-z ]+\d*(?=:)|\d+(?![^,])/i).with_object([[],[]]) do |s,(a,b)|
(s[0].match?(/\d/) ? b : a) << s
end
#=> [["Param 1", "Some text", "Example3", "Example4"],
# ["1", "2", "3", "4"]]

How to convert the position of an array into a single array?

What happens is that I have the following position of an array rows[0] = ["1", "2", "3", "4"] which stores certain data: what I want to do is to create a new array with the data that has the position 0 of the array rows so that, for example, I have a new vector = ["1", "2", "3", "4"], so that I could do, for example, console. log(new[0]); and have as output "1", and likewise with the other data of the new vector. I was thinking about doing it with some for or while loop, but I can't find the way to do it since row is of position 0.
you should try with destructuring
var rows = [];
rows[0] = ["1", "2", "3", "4"];
const [new] = rows
console.log(new[0]);

How do I check that every element in an array is greater than the one before it?

I'm using Ruby 2.4. I have an array of strings, which are themselves numbers. So something like
["1", "2", "3", "5"]
How do I check that the integer version of every element in the array (except the first) is greater than the one before it? So for instance the function performed on the above would return true, but an array like
["1", "5", "4", "6"]
would return false (because "4" is not greater than "5".
An alternative way to phrase your predicate is: "For all consecutive pairs of numbers, is it true that the second is greater than the first"? This can be almost directly expressed in code:
ary.map(&:to_i).each_cons(2).all? {|first, second| second > first }
By the way: this property is called "strict monotonicity".
You can use Enumerable#sort_by to see if the arr is already sorted by numerical value:
arr = ["1", "2", "3", "5"]
arr.uniq.sort_by(&:to_i) == arr
#=> true
If the elements are not unique, then the array fails automatically. Since that means two elements are of the same value i.e. one is not greater than the other.

Resources