Related
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));
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)
}
}
I have been messing around with the .sort() and .concat() functions trying to combine multiple arrays of numbers and text into one and chronologically order it. It seems to work fine if only numbers are input into the array but as soon as there is text it seems to place it randomly, in this case between 6 and 7. Also, if I remove the number 3 from the array, the number 4 ends up out of order after the text, both being between 9 and 10. I have no idea why it is doing this if anyone could help.
With only numbers:
var multiArray = [[2, 8, 1, 7, 9], [6, 3, 5, 4, 10]];
// returns 1,10,2,3,4,5,6,7,8,9
document.write(multiArray[0]
.concat(multiArray[1])
.sort()
+"<br/>");
// returns 1,2,3,4,5,6,7,8,9,10
document.write(multiArray[0]
.concat(multiArray[1])
.sort((a,b)=>a-b)
+"<br/>");
and with text
var multiArray = [[2, 8, 1, 7, 9], [6, 3, 5, "text", 4, 10]];
// returns 1,2,3,4,5,6,text,7,8,9,10
document.write(multiArray[0]
.concat(multiArray[1])
.sort((a,b)=>a-b)
+"<br/>");
and without 3
var multiArray = [[2, 8, 1, 7, 9], [6, 5, "text", 4, 10]];
// returns 1,2,5,6,7,8,9,text,4,10
document.write(multiArray[0]
.concat(multiArray[1])
.sort((a,b)=>a-b)
+"<br/>");
first, combine all arrays in a single array
var multiArray = [[2, 8, 1, 'foo', 7, '1', 9], [6, 5, 'text', 4, 'bar', 10]];
var flattenArray = [].concat(...multiArray); // [ 2, 8, 1, 'foo', 7, '1', 9, 6, 5, 'text', 4, 'bar', 10 ]
then sort separately numbers and strings
const sortedNumbers = flattenArray
.filter(n => typeof n === 'number')
.sort((a, b) => a - b);
const sortedStrings = flattenArray
.filter(n => typeof n === 'string')
.sort();
finally, concat both
const sorted = sortedNumbers.concat(sortedStrings); // [ 1, 2, 4, 5, 6, 7, 8, 9, 10, '1', 'bar', 'foo', 'text' ]
I assume you want strings after your numbers. Otherwise, simply invert the concatenation:
const sorted = sortedStrings.concat(sortedNumbers);
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
I have multiple array (max 15), each can max have 1800 objects.
I need to combine them into a single array, so that I then can apply a delimiter (',') to generate a csv file. The problem is when I combine them into a single array, it has to be sequentially combined, like first objects of each array should be inserted initially followed by the 2nd index of objects then 3rd and so on.
I'm able to achieve the result I want by using a for-in loop. However this doesn't very swifty. I feel it can be done in a much cleaner way using functional methods available in swift (using map, reduce and filter functions).
However I'm not able to combine them perfectly. Can anyone help me with using the swift functional methods to achieve the result.
P.S: Let me know if you want me to post the for-in loop code, but I believe that's not required.
Given 4 (or more) arrays
let list0: [Int] = [ 1, 2, 3, 6, 7, 8, 9 ]
let list1: [Int] = [ 10, 20, 30, 40, 50, 60, 70, 80, 90]
let list2: [Int] = [ 100, 200, 300, 400, 500, 600, 700, 800, 900]
let list3: [Int] = [ 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000 ]
enumerate each one and put them into another array
let lists = [
list0.enumerate().map { (index: $0, array: 0, value: $1) },
list1.enumerate().map { (index: $0, array: 1, value: $1) },
list2.enumerate().map { (index: $0, array: 2, value: $1) },
list3.enumerate().map { (index: $0, array: 3, value: $1) }
]
Now you can write
let sorted = lists
.flatten()
.sort { ($0.index, $0.array) < ($1.index, $1.array) }
.map { $0.value }
[1, 10, 100, 1000, 2, 20, 200, 2000, 3, 30, 300, 3000, 6, 40, 400, 4000, 7, 50, 500, 5000, 8, 60, 600, 6000, 9, 70, 700, 7000, 80, 800, 8000, 90, 900, 9000]
I would consider making this an extension for arrays of arrays (although note you cannot do this directly, see this Q&A). You could then use a combination of reduce(_:_:) along with both flavours of flatMap(_:) in order to sequentially merge your arrays by iterating through the lengths of the inner collections and extracting the elements at each given index.
extension Array where Element : RandomAccessCollection, Element.Index == Int, Element.IndexDistance == Element.Index {
func joinedByTransposing() -> [Element.Iterator.Element] {
// The maximum length of the inner collections. Obviously if the 2D array is
// guaranteed to be n*m, you can optimise by just taking the first inner
// collection's count (and obviously you'll want to check that the array isn't empty first).
let maxIndex = self.reduce(0, {$0 > $1.count ? $0 : $1.count})
// Iterates through the max length of the inner collections, joining the restantant collections
// from the transform below into a single array.
return (0..<maxIndex).flatMap { index in
// Iterate through each inner collection, getting the element at the current index of iteration,
// or returning nil if the index is out of bounds. This flatMap will filter out any nils.
// If the 2D array is guarenteed to be n*m, this can be replaced by self.map { $0[index] }
self.flatMap { innerArray in
// Simple bounds check to get the element at the given index, or nil if out of bounds
index < innerArray.count ? innerArray[index] : nil
}
}
}
}
let array0 = [1, 2, 3, 4 ]
let array1 = [10, 20, 30 ]
let array2 = [100, 200, 300, 6, 7]
let result = [array0, array1, array2].joinedByTransposing()
print(result)
// [1, 10, 100, 2, 20, 200, 3, 30, 300, 4, 6, 7]
It’s worth noting that this solution has an overall time complexity of O(n * m) – whereas solutions that utilise sorted(by:) will have a time complexity of at least O(n * m * log(n * m)). For large arrays, this extra cost may well be non-trivial.
Here is my functional approach to the problem that you describe in your post.
First I flatted the array using the enumerated method, which return a tuple with the element position inside the array and It's value.
After this, You have an array with this tuples, next step, sort this big array by the offset (position) value of each element.
Once the array is sorted you hace to extract the value with map function.
And final step, once we have an array with sorted values, You have to reduce it to a string with the reduce function
// A group of arrays
var array1: [Int] = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
var array2: [Int] = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
var array3: [Int] = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
var array4: [Int] = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
// This is **your** array
let bigOne = [ array1, array2, array3, array4 ]
// And here is the functional concatenation.
let flattedOne = bigOne.flatMap({ $0.enumerated() }).sorted(by: { $0.0 < $0.1 }).map({$0.element}).reduce("")
{
return $0.isEmpty ? "\($1)" : "\($0), \($1)"
}
print(flattedOne)
Here's another approach...
public func sort(compound array: [[Int]]) -> [Int]
{
let max_index: Int = array.map({ $0.count }).max()!
var sorted: [Int] = [Int]()
(0 ..< max_index).forEach({ index in
array.forEach()
{
if $0.count > index
{
sorted.append($0[index])
}
}
})
return sorted
}
// A group of arrays
var array1: [Int] = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 111, 112 ]
var array2: [Int] = [ 10, 20, 3, 4, 5, 6, 7, 8, 9, 10 ]
var array3: [Int] = [ 1000, 2000, 3, 4, 5, 600, 7, 8, 9, 10, 11 ]
var array4: [Int] = [ 100, 200, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
let bigOne: [[Int]] = [ array1, array2, array3, array4 ]
let sorted: [Int] = sort(compound: bigOne)
print(sorted)
And if you want the array as a CSV string...
print(sorted.reduce("") { return $0.isEmpty ? "\($1)" : "\($0), \($1)" })