I have a string:
key = "41521"
And I want to convert it into an array like this:
array = [41, 15, 52, 21]
I went about it like so:
array = []
array << key[0..1].to_i
array << key[1..2].to_i
array << key[2..3].to_i
array << key[3..4].to_i
What would be a better way?
key = "41521"
key.each_char.each_cons(2).map { |a| a.join.to_i }
#=> [41, 15, 52, 21]
or
key.gsub(/\d(?=(\d))/).with_object([]) { |s,a| a << (s<<$1).to_i }
#=> [41, 15, 52, 21]
or
a = []
e = key.each_char
#=> #<Enumerator: "41521":each_char>
loop { a << (e.next << e.peek).to_i }
a #=> [41, 15, 52, 21]
In #3 Enumerator#peek raises a StopInteration exception when the internal position of the enumerator is at the end (unless key is an empty string, in which case Enumerator#next raises the StopInteration exception). Kernel#loop handles the exception by breaking out of the loop.
key.gsub(/(?<=.)\d(?=.)/, '\&\&').scan(/\d{2}/).map(&:to_i)
# => [41, 15, 52, 21]
or
(0...key.length).map{|i| key[i, 2].to_i}
# => [41, 15, 52, 21, 1]
Not as short as some other answers, but for me, more easier to see the steps:
arr = key.chars.each_with_index
.reduce([]) {|s,(v,i)| s << (v + (key[i+1] || '')).to_i }
.select {|s| s.to_s.length > 1 }
# arr: [41, 15, 52, 21]
(0..(key.length-2)).map{|i| key.slice(i, 2)}
Related
Let's say we have an object with an array of numbers for each property:
const obj = {
line1: [2, 13, 7, 6, 14],
line2: [25, 16, 24, 27, 28],
line3: [41, 31, 32, 44, 42],
};
How can we Search for a specific number and Replace it with another number?
Let's say we would like to find number 44 and replace it with 88? In a modern JS way...
You can use loop to iterate on each key-value pair of the object, and then you can find and replace the number you want in the array. Keep in mind that if the number can be more than once in the same array you will have to loop on the array as well, otherwise you can use indexOf and assign the new value.
Here is an example:
const obj = {
line1: [2, 13, 7, 6, 14],
line2: [25, 16, 24, 27, 28],
line3: [41, 31, 32, 44, 42],
};
const changeNumber = (oldNum, newNum, obj) => {
for (const [key, arr] of Object.entries(obj)) {
const index = arr.indexOf(oldNum);
if (index > -1) {
arr[index] = newNum;
}
}
}
console.log(obj); // Before
changeNumber(44, 88, obj);
console.log(obj); // After
/* With duplicates entries */
const changeNumberDuplicate = (oldNum, newNum, obj) => {
for (const [key, arr] of Object.entries(obj)) {
let index = 0;
do {
index = arr.indexOf(oldNum, index);
if (index > -1) {
arr[index] = newNum;
}
} while (index > -1);
}
}
const objDup = {
line1: [2, 13, 44, 6, 44],
line2: [44, 16, 44, 27, 28],
line3: [41, 44, 32, 44, 42],
};
console.log(objDup); // Before
changeNumberDuplicate(44, 88, objDup);
console.log(objDup); // After
I'm trying to merge several arrays in javascript/typescript in angular, I need to output an array with the common values in all the arrays.
for eg:
arrayOne = [34, 23, 80, 93, 48]
arrayTwo = [48, 29, 10, 79, 23]
arrayThree = [23, 89, 48, 20, 63]
output: outputArr= [23, 48]
for getting common elements out of 2 arrays i'm filtering one array with the element from the next array.
return this.arrayOne.filter(el => this.arrayTwo.includes(el));
How do I do it effectively if I have to combine large number of arrays....?
Thanks in advance...
You could use multiple Set to quickly look up for each value among the different sets.
const intersection = <T>(arrays: T[][]): T[] => {
if (arrays.length == 0) return [];
if (arrays.length == 1) return arrays[0];
const sets = arrays.slice(1).map(array => new Set(array));
const result = [];
arrays[0].forEach(item => {
if (sets.every(set => set.has(item))) {
result.push(item);
}
});
return result;
};
const arrayOne = [34, 23, 80, 93, 48];
const arrayTwo = [48, 29, 10, 79, 23];
const arrayThree = [23, 89, 48, 20, 63];
const result = intersection([arrayOne, arrayTwo, arrayThree]);
console.log(result);
One approach is to create an initial set that contains the first array's elements. Then loop over the other arrays, converting them to sets and updating the initial set to retain the corresponding set intersection.
const commonElements = function(arrays) {
if (arrays.length == 0)
return [];
const intersection = new Set(arrays[0]);
for (const array of arrays) {
const set = new Set(array);
for (x of intersection) {
if (!set.has(x))
intersection.delete(x);
}
}
return Array.from(intersection);
};
Calling this function on the sample arrays in the question:
commonElements([
[34, 23, 80, 93, 48],
[48, 29, 10, 79, 23],
[23, 89, 48, 20, 63]])
Returns:
[23, 48]
So I want to convert in ruby
[{:user_id => 4}, {:user_id => 22}, {:user_id=>51}, {:user_id=>52}]
to
[4, 22, 51, 52]
Is there way of convert this?
As simple as possible: array.flat_map(&:values)
Very simple, let's use map to transform each item in something else
array.map { |item| item[:user_id] }
=> [4, 22, 51, 52]
So, I have made function that return publicKey and I need to duplicate it x times for later use.
For example: publicKey: [76, 152, 93, 102, 145, 181] and I need to duplicate it 3 times, so the end result should be [76, 152, 93, 102, 145, 181, 76, 152, 93, 102, 145, 181, 76, 152, 93, 102, 145, 181].
I have tried using var list3 = publicKey*x, but as you can imagine, it didn't work..
fun getPublicKey(privateKey: ArrayList<BigInteger>,
birthDay: BigInteger,
primNumb: BigInteger): ArrayList<BigInteger> {
val inversMod = birthDay.modInverse(primNumb)
//println(inversMod)
val publicKey: ArrayList<BigInteger> = ArrayList()
for (keyValue in privateKey){
val pagaiduValue = (keyValue * inversMod).mod(primNumb)
//println("($keyValue * $inversMod) mod $primNumb = $pagaiduValue")
publicKey.add(pagaiduValue)
}
return publicKey
}
Here's a short and simple solution:
inline fun <T> Iterable<T>.times(count: Int) = (1..count).flatMap { this }
Can be used like this:
val numbers = listOf(1, 2, 3)
val result = numbers.times(5)
println(result) // [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
Perhaps the naming could use some work, times could also be assumed to have the effect of multiplying each element by a given number, repeat could be a better alternative. Also, you might wanna define it on Array<T> and the primitive array types (IntArray, etc) as well.
I have an array of ages.
I want to split the array in to 4 subarrays by the age value.
A -> 0...25
B -> 26...50
c -> 51...75
d -> 76 +
I have no problem iterating through the array and append to different arrays by the age value.
let subArrays: [[Int]] = [[], [], [], []]
for age in ages {
switch age {
case 0...25:
subArrays[0].append(age)
case 26...50:
subArrays[1].append(age)
case 51...75:
subArrays[2].append(age)
default:
subArrays[3].append(age)
}
}
My questions is:
Is there a cleaner way to do this using map, split or any other function.
Thanks
This doesn't use map or anything fancy but you can easily eliminate the switch:
var subArrays: [[Int]] = [[], [], [], []]
for age in ages {
subArrays[min((age - 1) / 25, 3)].append(age)
}
The use of min ensures all values of 76 and greater go into the last slot.
And to test, with all boundary cases, try:
let ages = [ 50, 67, 75, 76, 25, 12, 26, 51, 99, 45, 0, 120, 16 ]
And then:
print(subArrays)
Gives:
[[25, 12, 0, 16], [50, 26, 45], [67, 75, 51], [76, 99, 120]]
A more generic version that does not depend on any mathematical property of your ranges:
func split<T>(array: [T], ranges: [CountableClosedRange<T>]) -> [[T]] {
var result = Array(repeating: [T](), count: ranges.count)
for element in array {
if let subIndex = ranges.index(where: { $0 ~= element }) {
result[subIndex].append(element)
}
}
return result
}
let ages = [10, 20, 30, 40, 50, 60]
let subarrays = split(array: ages, ranges: [0...25, 26...50, 51...75, 76...Int.max])
Note that it does not check for overlapping ranges.
Based on rmaddy's answer (practically the same) but within one line:
let subs = (0...3).map { sub in ages.filter { sub == min(($0 - 1) / 25, 3) } }