Im wondering if it is possible to insert an element at index 1 but not index 0 in swift like this:
var array = [String]()
array.insert("cow", atIndex: 1)
but every time I try I get the old fatal error: Array index out of range error message.
Is there anyway around this problem? Any suggestions would be greatly appreciated! Thanks!
If you make it an array of optionals and initialize the number of elements you want first, you can get close.
var array = [String?]()
for i in 0...5 {
array.append(nil)
}
array.insert("cow", atIndex: 1)
If you really want the index to be specific, rather than just the next available position in the array, you should use a dictionary with Int keys.
var dict = [Int:String]()
dict[1] = "Cow"
dict[5] = "Chicken"
You can create a custom list. You will need to add some checking to make sure items aren't null or out of index, etc.
void Main()
{
var list = new CustomList<string>();
list.Add("Chicken");
list.Add("Bear");
list[1] = "Cow";
list[1].Dump(); //output Cow
}
public class CustomList<T>
{
IList<T> list = new List<T>();
public void Add(T item)
{
list.Add(item);
}
public T this[int index]
{
get
{
return list[index - 1];
}
set
{
list[index - 1] = value;
}
}
}
Literally you can't.
An item can be inserted up to the maximum index index(max) = array.count, in case of an empty array at index 0.
Related
var brachNames = ["AP","AP","AP","AS","AS","AS","BR","BR","BR"]
var overAllTaget = ["84","84","84","84","84","84","84","84","84"]
var overAllSold = ["135","135","135","135","135","135","135","135","135"]
extension Array where Element : Hashable {
func removeDups() -> [Element] {
var uniquedElements = Set<Element>()
return filter { uniquedElements.insert($0).inserted }
}
}
I want this type of output - [AP,84,135,AS,84,135,BR,84,135]
Since you've 3 different Arrays, you need to first combine these to get an Array of Arrays using zip(_:_:) and map(_:), i.e.
var arr = zip(brachNames, zip(overAllTaget, overAllSold)).map { [$0.0, $0.1.0, $0.1.1] }
Now, use Set to filter out the duplicates. Then use flatMap(_:) to get a single result Array, i.e.
let result = Array(Set(arr)).flatMap{ $0 } //["AP", "84", "135", "AS", "84", "135", "BR", "84", "135"]
Note: Set is unordered. So, the sequence of the result might change.
Another approach would be to create a struct with the required fields (brachName, overallTarget, overallSold), comply to Hashable and apply something like this:
https://www.hackingwithswift.com/example-code/language/how-to-remove-duplicate-items-from-an-array
This way you could keep the order, if that's important.
It would be much better to work with an array of a custom type instead of 3 different arrays of data to make the code clearer and to avoid simple mistakes when accessing the data. Below is an example of such solution using a struct to hold the data
struct BranchData: Hashable {
let branchName: String
let overallTarget: Int
let overallSold: Int
}
var set = Set<BranchData>()
for (index, branch) in brachNames.enumerated() {
guard index < overAllSold.count, index < overAllTaget.count else {
break
}
set.insert(BranchData(branchName: branch, overallTarget: Int(overAllTaget[index]) ?? 0, overallSold: Int(overAllSold[index]) ?? 0))
}
To support the specific output with all values in an array we can add a computed property
extension BranchData {
var propertyArray: [String] {
[branchName, String(overallTarget), String(overallSold)]
}
}
let output = set.flatMap { $0.propertyArray }
or a more direct approach
let output = set.flatMap { [$0.branchName, $0.overallTarget, $0.overallSold] }
So I recently learned that you can use objects as a data type in an array.
So what I need to do is loop through this array, and add each age, then divide age sum by the length of the array to get an average age of all people. Thing is I don't understand how you would call a given key.
I understand that to call the first object, you would write "people[0]" but I have no idea how to get the key from that object and pass that to a function.
let people=[ {name:'Don', Age:23},
{name:'Ron', Age:21},
{name:'Juan', Age:20}
]
// return /people.length
If you want to add the age and then divide by length of array to get avg value, in this case you can simply used Array.map()
let people=[
{name:'Don', Age:23},
{name:'Ron', Age:21},
{name:'Juan', Age:20}]
//Sum
let sum = 0;
//Map
people.map((value)=> {
sum += value.Age;
})
//Average Result
let avg_Age = sum / people.length
console.log('Average Age', avg_Age)
hope this may help.
let people=[ {name:'Don', Age:23},
{name:'Ron', Age:21},
{name:'Juan', Age:20}
];
var totalPeople = people.length;
var totalAge = 0
var averageAge = 0;
for (var key in people) {
// skip loop if the property is from prototype
if (!people.hasOwnProperty(key)) continue;
var obj = people[key];
for (var prop in obj) {
// skip loop if the property is from prototype
if (!obj.hasOwnProperty(prop)) continue;
if(prop == 'Age') {
totalAge += obj[prop];
}
}
}
averageAge = totalAge / totalPeople;
alert(averageAge);
You can use below code to traverse through the object and access keys:
let sum = 0;
for(let i=1;i<=people.length;i++) {
sum = sum + people[i-1].Age;
}
console.log(sum/people.length);
//output
21.333333333333332
You can also use foreach method to traverse the array.
https://www.w3schools.com/jsref/jsref_obj_array.asp
Go through this link here you can find all the methods for array/object manipulation.
To get the keys call Object.keys(people[0])
Please take a look Object.keys method
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
Func to see if two arrays have some same values:
func hasAllSame(largeCombinedArry:[Int], wantToKeep: [Int])->Bool{
var howManySame = [Int]()
for intElement in largeCombinedArry{
if wantToKeep.contains(intElement){
howManySame.append(intElement)
}
}
howManySame.sort()
if wantToKeep == howManySame{
print("These are the same!")
return true
}
else{
print("These are NOT same!")
return false
}
}
Array of tuples declared like this:
var TuplesArry:[(score: Double, value: [Int])] = []
Array filled thusly:
for (arry1, score) in zip(arryOfArrays, AllScores) {
let calculatedDiff = otherValue - score
TuplesArry.append((score: calculatedDiff, value: arry1))
}
var arrayForComparison = [8,9,7,6]
arrayForComparison.sort()
Error occurs here after several iteration at function call hasAllSame()
for i in 0..<TuplesArry.count{
if hasAllSame(largeCombinedArry: TuplesArry[i].value, wantToKeep:
arrayForComparison){
//do nothing
}
else{
/*
want to remove tuple that does not have all elements that are
in arrayForComparison
*/
TuplesArry.remove(at: i)
}
}
This code seems to be working but it seems like tuplesArry.count continues to decrease and iterator i continues to increase until error occurs "fatal index out of range"
My goal is to remove a tuple from the array of tuples if it's value does not meet criteria.
I've also tried something like:
for tuple in TuplesArry{
if hasAllSame(largeCombinedArry: tuple.value, wantToKeep:
arrayForComparison){
//do nothing
}
else{
//this does NOT work
let index = TuplesArry.index(of:tuple)
TuplesArry.remove(at: index)
}
}
The immediate issue is that you need to iterate in reverse to avoid the "index out of range" issue.
The much simpler solution is to use filter on your array. Then you entire for loop can be replaced with:
TouplesArry = TouplesArry.filter { hasAllSame(largeCombinedArry: $0.value, wantToKeep: arrayForComparison) }
I have index out of range error when i delete object from my array. There is my code. It is an Elevator function which takes object of Floor class and works with array of objects of Passenger class on this floor. I create a temporary copy of object of current floor and then I go along array of this copy and if object is suitable for the conditions we push this object to Elevator array of passengers and delete it by index from original array of current floor object. If this matters, I use the Equatable protocol and created a function to compare.
Thanks for any answers.
class Passenger: Equatable{...}
func ==(l: Passenger, r: Passenger) -> Bool {
return l === r
}
func checkFloor(f: Floor){
var tempFloor = f
var pass = passengers
for i in 0..<passengers.count {
if(passengers.isEmpty){
break
}
if(pass[i].getFloor()==f.getIdFloor()){
f.peoples.append(pass[i])
f.peoples[f.peoples.count - 1].setDirection(who: "nothing")
//if var index = passengers.index(of: pass[i]) {
if let index = searchInArray(who: passengers, who: pass[i]) {
passengers.remove(at: index)
}
}
}
// in this part I have a problem
for i in 0..<tempFloor.countOf() {
if(f.peoples.isEmpty || passengers.count >= capacity){
break
}
if(tempFloor.peoples[i].getDirection()==tempFloor.peoplesDirection()
){
passengers.append(tempFloor.peoples[i])
if let index = f.peoples.index(of: tempFloor.peoples[i]) {
if (index >= 0 && index < f.peoples.count) {
//print(index)
f.peoples.remove(at: index) // index out of range error
}
}
}
}
}
You are removing items whilst enumerating a range, so the range is changing (potentially often) but this wont update for i in 0..<tempFloor.countOf()
When you remove an item from an array, each item after that index changes its index and the count is reduced. so if you plan to do this, it's usually best to enumerate the array backwards, so the removal of the current item will not affect what your doing next.
To demonstrate, try this code in a playground
var arr = [1,2,3,4,5,6,7,8,9,10]
for (index, item) in arr.enumerated().reversed() {
if item % 2 == 0 {
arr.remove(at: index)
}
}
print(arr)
It will iterate over the items in the array backwards and remove any that are even, and will output:
"[1, 3, 5, 7, 9]\n"
I have created an array as shown below
protected function getMyArray(dataArray:Array):Array
{
var labelList:Array=new Array;
for each (var property:Object in dataArray)
{
if (labelList[property.bucketTime] != property.bucketTime)
labelList[property.bucketTime]=property.bucketTime;
}
return labelList;
}
Is it possible to sort the array labelList based on property.bucketTime?
Edit: Sample input dataArray will be like this :
var tempObj:Object = new Object;
tempObj.bucketTime = DateField.stringToDate("30-01-2010", "DD-MM-YYYY").time;
tempObj.score = 76;
dataArray.addItem(tempObj);
tempObj = new Object;
tempObj.bucketTime = DateField.stringToDate("13-02-2010", "DD-MM-YYYY").time;
tempObj.score = 21;
dataArray.addItem(tempObj);
tempObj = new Object;
tempObj.bucketTime = DateField.stringToDate("30-03-2010", "DD-MM-YYYY").time;
tempObj.score = 10;
tempArry.addItem(tempObj);
Unless bucketTime is a number; then you aren't actually populating the array. You're just adding properties to the Array Object, almost like it were a Dictionary. I've seen a Dictionary called Associative Array's and Structures in other languages.
If that is the case, an you're using the Array class as a dictionary, then there is no way to sort it. The very nature of such a structure is that they are not sortable.
However, if property.bucketTime is a number, and you are trying adding items to the array as if they were an array, you can sort using the Array.sort or Array.sortOn methods.
Atlast I sorted the labelList Array.Please find my solution below. Let me know if there is any better way to achieve this.
var termObject:Object = ObjectUtil.getClassInfo(labelList);
var termsArray:Array = termObject.properties;
var sortedColumnArray:Array = new Array;
for each(var term:Object in termsArray){
if(labelList.hasOwnProperty(term)){
sortedColumnArray.push(labelList[term]);
}
}