I am trying to split array into pairs. I am able to split into consecutive pair but I want to split into pair which includes previous value as mentioned in Results
Logic to split in consecutive pair, which I tried.
extension Array {
func chunks(_ chunkSize: Int) -> [[Element]] {
return stride(from: 0, to: self.count, by: chunkSize).map {
Array(self[$0..<Swift.min($0 + chunkSize, self.count)])
}
}
Array:
["1", "2", "3", "4", "5", "6", "7", "8", "9"]
Results:
[["1", "2"], ["2", "3"], ["3", "4"], ["4", "5"], ["6", "7"], ["7", "8"], ["8", "9"]]
How about this:
let a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9]
let pairs = Array(zip(a, a.dropFirst())).map {[$0.0, $0.1] }
print(pairs)
That outputs
[[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9]]
Edit:
If you want arbitrary chunk-size, you could write the extension like this:
extension Array {
func chunks(_ chunkSize: Int, includePartialChunk: Bool = true) -> [[Element]] {
var indexes = Array<Int>(stride(from: 0, to: count, by: chunkSize - 1))
if includePartialChunk,
let last = indexes.last,
last < count - 1 {
indexes.append(count-1)
}
return zip(indexes, indexes.dropFirst()).map {Array(self[$0.0...$0.1])}
}
}
Use the parameter includePartialChunk to tell the function if you want to include a "partial chunk" at the end when the array size is not an even multiple of the chunk-size. If true (The default) it returns a last chunk that is smaller than chunkSize but goes to the end of the array. If false, it only returns full-sized chunks, but will skip array elements at the end that don't fit into a full-sized chunk.
(I'll have to study Leo's UnfoldSequence version and see if I can adapt my code to that.)
Not a direct answer to the question but the elements of the sequence should be computed lazily. You should use Swift UnfoldSequence type as follow:
extension Collection {
var unfoldedNeighbors: UnfoldSequence<SubSequence,Index> {
sequence(state: startIndex) { start in
guard start < endIndex else { return nil }
guard let end = index(start, offsetBy: 2, limitedBy: endIndex) else {
return nil
}
defer { formIndex(after: &start) }
return self[start..<end]
}
}
var neighborsSubsequences: [SubSequence] {
.init(unfoldedNeighbors)
}
var neighborsArrays: [[Element]] {
unfoldedNeighbors.map([Element].init)
}
}
Usage:
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for neighbors in numbers.unfoldedNeighbors {
print(neighbors)
}
If you need control the number of elements of each subsequence and also if it includes the tail or not:
extension Collection {
func unfoldedNeighbors(limitedTo length: Int, includesTail: Bool = false) -> UnfoldSequence<SubSequence,Index> {
sequence(state: startIndex) { start in
guard start < endIndex else { return nil }
guard let end = index(start, offsetBy: length, limitedBy: endIndex) else {
if includesTail {
defer { formIndex(&start, offsetBy: length-1, limitedBy: endIndex) }
return self[start...]
}
return nil
}
defer { formIndex(&start, offsetBy: length-1, limitedBy: endIndex) }
return self[start..<end]
}
}
func neighborsSequences(limitedTo length: Int, includesTail: Bool = false) -> [SubSequence] {
.init(unfoldedNeighbors(limitedTo: length, includesTail: includesTail))
}
func neighborsArrays(limitedTo length: Int, includesTail: Bool = false) -> [[Element]] {
unfoldedNeighbors(limitedTo: length, includesTail: includesTail).map([Element].init)
}
}
Usage:
let numbers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for neighbors in numbers.unfoldedNeighbors(limitedTo: 3, includesTail: true) {
print(neighbors)
}
This will print:
[1, 2, 3]
[3, 4, 5]
[5, 6, 7]
[7, 8, 9]
[9, 10]
let neighborsSequences = a.neighborsSequences(limitedTo: 3, includesTail: true) // [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 10]] of type [Array<Int>.SubSequence]
let neighborsArrays = a.neighborsArrays(limitedTo: 3, includesTail: true) // [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 10]] of type [[Int]]
This operation goes by windows. It does exactly what you've requested, for count 2…
import Algorithms
Array(["1", "2", "3", "4", "5", "6", "7", "8", "9"].windows(ofCount: 2))
…but it's unclear if it does what you want for other counts.
I've been trying to create 2D arrays from an array dynamically with a function; however, I couldn't break out of the ES3 old school approach. Does anybody know how to refactor the following code using the ES6 approach?
const nums = [1,2,3,4,5,6,7,8,9,10,11,12];
const letters = ['a','b','c','d','e','f','g','h','i'];
function create2D(arr,set) {
const result = [];
for (let i = 0; i < arr.length; i+=set) {
const rows = arr.slice(i,i+set);
result.push(rows);
}
return result;
}
console.log(create2D(nums,4)); // [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ] ]
console.log(create2D(letters,3)); // [ [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ], [ 'g', 'h', 'i' ] ]
I've only gotten this far with "reduce" and couldn't find out how to replicate the addition assignment "i+=set" from the for loop. This is what I have so far...
function create2D(arr,set) {
return arr.reduce((result,item,i) => {
result.push(arr.slice(i,i+set));
return result;
},[]);
}
console.log(create2D(nums, 4)); // [ [1, 2, 3, 4],[2, 3, 4, 5],[3, 4, 5, 6], ...]
You were pretty close. Just need to modify it slightly:
const nums = [1,2,3,4,5,6,7,8,9,10,11,12];
const letters = ['a','b','c','d','e','f','g','h','i'];
function create2D(arr,set) {
return arr.reduce((result,item,i) => {
let startVal = i*set //We want to jump through the startPoints. Not iterate through them all
if (startVal < arr.length-1) {
result.push(arr.slice(startVal,startVal+set));
}
return result;
}, []);
}
console.log(create2D(nums, 4)); // [ [1, 2, 3, 4],[2, 3, 4, 5],[3, 4, 5, 6], ...]
console.log(create2D(nums, 3));
console.log(create2D(letters, 3));
I have this array right here and I need to get the "id" of each object
[{ id: 1, points: 60 }, { id: 2, points: 20 }, { id: 3, points: 95 }, { id: 4, points: 75 }]
customers = [{ id: 1, points: 90 }, { id: 2, points: 20 }, { id: 3, points: 70 }, { id: 4, points: 40 }, { id: 5, points: 60 }, { id: 6, points: 10}]
I know how to go through the whole array with
#scores.each_with_index{ |score, index| }
However, I haven't found a way to get the objects's points.
Perhaps you are looking for the following.
customers = [
{ id: 1, points: 90 }, { id: 2, points: 20 },
{ id: 3, points: 70 }, { id: 4, points: 40 },
{ id: 5, points: 60 }, { id: 6, points: 10}
]
h = customers.each_with_object({}) do |g,h|
id, points = g.values_at(:id, :points)
h[id] = points
end
#=> {1=>90, 2=>20, 3=>70, 4=>40, 5=>60, 6=>10}
This allows you to easily extract information of interest, such as the following.
h.keys
#=> [1, 2, 3, 4, 5, 6]
h.values
#=> [90, 20, 70, 40, 60, 10]
h[2]
#=> 20
h.key?(5)
#=> true
h.key?(7)
#=> false
h.value?(70)
#=> true
h.value?(30)
#=> false
What you called score is actually an hash like { id: 1, points: 60 } and I'm going to call it item
So, let's try
#scores.each_with_index do |item, index|
puts "#{index + 1}: id #{item[:id]}, points #{item[:points]}"
end
So, I have this array right here and I need to get the id of each object
In order to transform each element of a collection, you can use Enumerable#map (or in this case more precisely Array#map):
customers.map { _1[:id] }
#=> [1, 2, 3, 4, 5, 6]
This given construct is an array of objects so we need to individually iterate through each element and print out the value present in the objects. The following code shows how we can do it:
customers.each{|obj| p obj[:id].to_s+" "+ obj[:points].to_s }
Here we iterate through each element and print out individual entities of the hash using the obj[:id]/obj[:points] (obj being each individual object here.)
What about something like this?
customers.map(&:to_proc).map{ |p| [:id, :points].map(&p) }
=> [[1, 90], [2, 20], [3, 70], [4, 40], [5, 60], [6, 10]]
How to remove a value from dictionary with array of values. I have response from server like below:
[
"business_proof":[
0,
0,
0,
0,
0,
0,
0,
0,
-1,// business_proof contains -1, I want to remove this key like wise any other contains
0,
0
],
"reference_proof":[
1,
2,
1
],
"vehicle_proof":[
1,
1,
2
],
"previous_loan_track":[
2,
2,
0,
0,
2,
2
],
"banking_proof":[
1,
1
],
"income_proof":[
0,
0,
2,
0,
2,
1,
2,
0,
0
],
"signature_proof":[
2,
2,
1,
2,
2,
2
],
"employment_proof":[
2,
1,
2,
2,
2,
2,
2
],
"guarantor_proof":[
1,
2,
2
],
"pdc_proof":[
1,
0
],
"address_proof":[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
3
],
"age_proof":[
2,
2,
2,
2,
2,
2,
1,
2
],
"contact_proof":[
0,
2,
2
],
"photo_id_proof":[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
]
Second reponse
[
"signature_proof":[
"pan_card",
"driving_licence",
"accepted_documents",
"passport",
"cancelled_cheque",
"bank_report"
],
"guarantor_proof":[
"accepted_documents",
"co_applicant",
"guarantor"
],
"previous_loan_track":[
"housing_loan",
"vehicle_loan",
"over_draft_limit",
"accepted_documents",
"business_loan",
"personal_loan"
],
"address_proof":[
"bank_statement",
"voter_id",
"rental_agreement",
"eb_bill",
"registration_document",
"hr_letter",
"driving_licence",
"property_tax_receipt",
"telephone_bill",
"cc_statement",
"gas_bill",
"aadhaar_card",
"passport",
"ration_card",
"accepted_documents"
],
"vehicle_proof":[
"vehi_insurance",
"vehi_rc",
"accepted_documents"
],
"business_proof":[
"business_commencement_certificate",
"ssi_msme_certificate",
"business_transactions",
"mou",
"aoa",
"gst_no",
"tan_no",
"business_agreements",
"accepted_documents",
"shop_and_establishment_certificate",
"incorporation_certificate"
],
"banking_proof":[
"bank_statement",
"accepted_documents"
],
"income_proof":[
"form_16",
"profit_loss_statement",
"rental_income_proof",
"payslip",
"income_in_cash_proof",
"accepted_documents",
"brokerage_income_proof",
"it_returns",
"audited_balance_sheet"
],
"reference_proof":[
"ref2",
"accepted_documents",
"ref1"
],
"employment_proof":[
"employee_id_card",
"accepted_documents",
"payslip",
"relieving_letter",
"comp_app_letter",
"hr_letter",
"epf_no_uan_no"
],
"age_proof":[
"employee_id_card",
"ration_card",
"pan_card",
"passport",
"voter_id",
"school_certificate",
"accepted_documents",
"aadhaar_card"
],
"contact_proof":[
"accepted_documents",
"landline_bill",
"mobile_bill"
],
"photo_id_proof":[
"employee_id_card",
"nrega_card",
"ration_card",
"bank_passbook",
"pan_card",
"passport",
"voter_id",
"driving_licence",
"accepted_documents",
"aadhaar_card"
],
"pdc_proof":[
"cheque_book",
"accepted_documents"
]
]
Both are array of dictionary, Both will have same key only. I know this structure is completely wrong.
business_proof only contains - 1, so i want to remove both places.
Here i need to remove key and values if anyone key values contains -1.
I am trying like this but it shows compiler error
finalValueArray.removeAll(where: { $0.contains(-1) })
You can use filter as far as I understand
var filteredItems = object.filter { !$0.value.contains(-1)}
You can get all elements which contain -1
var minusOneItems = object.filter { $0.value.contains(-1)}
and than
for negativeItem in minusOneItems {
object.removeValue(forKey: negativeItem.key)
}
It depends what you need.
You can simply use a combination of forEach and contains on the dictionary like so,
var dictionary = ["business_proof": [0, 0, 1, -1, 2, -1], "reference_proof": [1, 2, 1], "vehicle_proof": [-1, 0, 0, 2]]
dictionary.forEach { (key,value) in
dictionary[key] = value.contains(-1) ? nil : value
}
print(dictionary) //["reference_proof": [1, 2, 1]]
Or you can simply apply filter on dictionary like,
dictionary = dictionary.filter({ !$0.value.contains(-1) })
print(dictionary) //["reference_proof": [1, 2, 1]]
You can filter your dictionary to remove the entries that contains -1 in their value.
let filteredArrayOnDict = dataDict.filter { value.contains{ $0 != -1 } }
The filteredArrayOnDict is the array of tuples. Now if you want to create a dictionary from it. You can do this way:
let filteredDictionary = filteredArrayOnDict.reduce(into: [:]) { $0[$1.0] = $1.1}
Now you have the only the entries in filteredDictionary that doesn't have -1 in their value.
You can use while loop to remove all key-value pairs which contain -1 from both dictionaries.
var dict1 = ["business_proof":[0,0,0,0,0,0,0,0,-1,0,0],"reference_proof":[1,2,1],"vehicle_proof":[1,1,2],"previous_loan_track":[2,2,0,0,2,2],"banking_proof":[1,1],"income_proof":[0,0,2,0,2,1,2,0,0],"signature_proof":[2,2,1,2,2,2],"employment_proof":[2,1,2,2,2,2,2],"guarantor_proof":[1,2,2],"pdc_proof":[1,0],"address_proof":[2,2,2,2,2,2,2,2,2,2,2,2,2,2,3],"age_proof":[2,2,2,2,2,2,1,2],"contact_proof":[0,2,2],"photo_id_proof":[2,2,2,2,2,2,2,2,2,2]]
var dict2 = ["signature_proof":["pan_card","driving_licence","accepted_documents","passport","cancelled_cheque","bank_report"],"guarantor_proof":["accepted_documents","co_applicant","guarantor"],"previous_loan_track":["housing_loan","vehicle_loan","over_draft_limit","accepted_documents","business_loan","personal_loan"],"address_proof":["bank_statement","voter_id","rental_agreement","eb_bill","registration_document","hr_letter","driving_licence","property_tax_receipt","telephone_bill","cc_statement","gas_bill","aadhaar_card","passport","ration_card","accepted_documents"],"vehicle_proof":["vehi_insurance","vehi_rc","accepted_documents"],"business_proof":["business_commencement_certificate","ssi_msme_certificate","business_transactions","mou","aoa","gst_no","tan_no","business_agreements","accepted_documents","shop_and_establishment_certificate","incorporation_certificate"],"banking_proof":["bank_statement","accepted_documents"],"income_proof":["form_16","profit_loss_statement","rental_income_proof","payslip","income_in_cash_proof","accepted_documents","brokerage_income_proof","it_returns","audited_balance_sheet"],"reference_proof":["ref2","accepted_documents","ref1"],"employment_proof":["employee_id_card","accepted_documents","payslip","relieving_letter","comp_app_letter","hr_letter","epf_no_uan_no"],"age_proof":["employee_id_card","ration_card","pan_card","passport","voter_id","school_certificate","accepted_documents","aadhaar_card"],"contact_proof":["accepted_documents","landline_bill","mobile_bill"],"photo_id_proof":["employee_id_card","nrega_card","ration_card","bank_passbook","pan_card","passport","voter_id","driving_licence","accepted_documents","aadhaar_card"],"pdc_proof":["cheque_book","accepted_documents"]]
while let invalid = dict1.first(where: { $0.value.contains(-1) }) {
dict1.removeValue(forKey: invalid.key)
dict2.removeValue(forKey: invalid.key)
}
print(dict1)//["reference_proof":[1,2,1],"vehicle_proof":[1,1,2],"previous_loan_track":[2,2,0,0,2,2],"banking_proof":[1,1],"income_proof":[0,0,2,0,2,1,2,0,0],"signature_proof":[2,2,1,2,2,2],"employment_proof":[2,1,2,2,2,2,2],"guarantor_proof":[1,2,2],"pdc_proof":[1,0],"address_proof":[2,2,2,2,2,2,2,2,2,2,2,2,2,2,3],"age_proof":[2,2,2,2,2,2,1,2],"contact_proof":[0,2,2],"photo_id_proof":[2,2,2,2,2,2,2,2,2,2]]
print(dict2)//["signature_proof":["pan_card","driving_licence","accepted_documents","passport","cancelled_cheque","bank_report"],"guarantor_proof":["accepted_documents","co_applicant","guarantor"],"previous_loan_track":["housing_loan","vehicle_loan","over_draft_limit","accepted_documents","business_loan","personal_loan"],"address_proof":["bank_statement","voter_id","rental_agreement","eb_bill","registration_document","hr_letter","driving_licence","property_tax_receipt","telephone_bill","cc_statement","gas_bill","aadhaar_card","passport","ration_card","accepted_documents"],"vehicle_proof":["vehi_insurance","vehi_rc","accepted_documents"],"banking_proof":["bank_statement","accepted_documents"],"income_proof":["form_16","profit_loss_statement","rental_income_proof","payslip","income_in_cash_proof","accepted_documents","brokerage_income_proof","it_returns","audited_balance_sheet"],"reference_proof":["ref2","accepted_documents","ref1"],"employment_proof":["employee_id_card","accepted_documents","payslip","relieving_letter","comp_app_letter","hr_letter","epf_no_uan_no"],"age_proof":["employee_id_card","ration_card","pan_card","passport","voter_id","school_certificate","accepted_documents","aadhaar_card"],"contact_proof":["accepted_documents","landline_bill","mobile_bill"],"photo_id_proof":["employee_id_card","nrega_card","ration_card","bank_passbook","pan_card","passport","voter_id","driving_licence","accepted_documents","aadhaar_card"],"pdc_proof":["cheque_book","accepted_documents"]]
Create a struct and initialize the struct objects with both dictionary values. Then store the struct objects in an array. Now you can filter the array by its values
struct Proof {
var title: String
var arr: [Int]
var documents: [String]
}
var proofs = [Proof]()
dict1.forEach {
if let docs = dict2[$0.key] {
proofs.append(Proof(title: $0.key, arr: $0.value, documents: docs))
}
}
print(proofs)
let validProofs = proofs.filter { !$0.arr.contains(-1) }
print(validProofs)
Enumerate the index dictionary, look for occurrences of -1 and filter the indices. Then reverse the found indices and remove the items in both arrays. The code considers that both dictionaries are value types
var indexDict = ["business_proof":[0,0,0,0,0,0,0,0,-1,0,0] ...
var valueDict = ["signature_proof":["pan_card","driving_licence","accepted_documents","passport","cancelled_cheque","bank_report"] ...
for (key, value) in indexDict {
let foundIndices = value.indices.filter({value[$0] == -1})
for index in foundIndices.reversed() {
indexDict[key]!.remove(at: index)
valueDict[key]!.remove(at: index)
}
}
My ultimate goal is to get an array of Ints extracted from a String inputted in a textfield. For this I created a function whose parameter is a String. I use a for-loop to get all the characters from the textfield into an array. Then I loop through the array and append only the numbers (if they're <= 24) to a new array. When I print the array with just numbers, I get the first element of array1 repeating. Why is this happening?
var array1 = [String]()
var array2 = [Int]()
func getDigits (userInput: String) {
for element in userInput {
array1.append(String(element))
}
var mx = 0
var fx = 1
func findNumbers() {
for number in 1...24 {
if array1[mx] == "\(fx)" {
array2.append(Int(String(array1[mx]))!)
} else {
fx += 1
findNumbers()
}
}
}
findNumbers()
print (array2)
}
getDigits(userInput: "4-5")
Output: [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
This will support multi-digit numbers in your input string, and also filter out-of-range values.
import Foundation
func parseNumbers (userInput: String, splitBy: String, min: Int, max: Int) -> Array<Int> {
let separators = CharacterSet(charactersIn: splitBy)
let numericStrings = userInput.components(separatedBy: separators)
var numArray = [Int]()
for item in numericStrings {
if let number = Int(item) {
if (number >= min) && (number <= max) {
numArray.append(number)
}
}
}
return numArray
}
print(parseNumbers(userInput: "5:hello,34-7 12;103,abc", splitBy: " -:,;", min:1, max:24))
output: [5, 7, 12]
try this
func getDigits (userInput: String) {
let splitsCharacters = ",;:- "
let seperators = CharacterSet(charactersIn: splitsCharacters)
let updateInput = userInput.components(separatedBy: seperators)
print(array1)
func findNumbers() {
for item in updateInput {
if let number = Int(item) {
if number <= 24{
array2.append(number)
}
}
}
}
findNumbers()
print (array2)
}
getDigits(userInput: "4-5 hello, 34;12,23")
Output : [4, 5,12,23]
I am not sure what you are trying to do but you can try something like
Swift 4
func getDigits (userInput: String) {
var resultArray = [Int]()
for char in userInput {
if let number = Int("\(char)"), number < 24 {
resultArray.append(number)
}
}
print(resultArray)
}
testing
getDigits(userInput: "4-5")
//prints => [4, 5]
You need just 1 array to hold the numbers
Note: in swift for the string is array type so you can loop on it directly, but for earlier versions you can use:
for char in userInput.characters {
}
to get the array of string characters