i have a table that is multiple selected allow. first time user select some row . second time user come beck this page deselect some row and may be selected some row or not . but i need to hold previous selected rows . that row indicated price . so i need to track price that is the reason table view selected row i am tracking .
Here i my declaration array empty :
var groupSelectedOldPrice : [String] = []
here is my table row selected index item price append to the array:
if addon?.isSelect == true {
cell.accessoryType = .checkmark
groupSelectedOldPrice[indexPath.row] = (addon?.price)! // Index out of range
}
when user press done button :
let selectedUserRows = self.tableView.indexPathsForSelectedRows
if let _selectedUserRows = selectedUserRows {
for select in _selectedUserRows {
print(select.row)
let dishprice = Double((dish?.price)!)! - Double(groupSelectedOldPrice[select.row])!
dish?.price = "\(dishprice)"
}
}
i am not sure How i can achieved this . should I use dictionary for key value
You are getting Array index is out of range error because you are trying to insert at discrete indexes (more like skipping intermediate indexes. But it doesn't work this way. You just can't have an array like ["a", "b", _ , _ , "g", "u", _ , _ , "y"])
Let's do one thing. You maintain a counter var, insert at that counter's position and then increment that counter. Something like:
var counter: Int = 0
...
groupSelectedOldPrice.insert("your string" at:counter)
counter = counter +1
...
EDIT
(Answered according to what you asked for)
To achieve your requirement, you can maintain a Dictionary. A Dictionary where key will be your indexpath.row and value will be your String. Pretty much like:
var dic: [Int:String] = [:] // it's your declaration
....
....
dic[indexpath.row] = "your string" // when you try to fill your dictionary
You can insert your element at a specific index of array
let index = 1
yourArray.insert("Your String", at: index)
Related
I have an array of thousands of rows with an element of "Order Number." I want to filter that array where that Order Number does not exist in a Dataverse table column.
I've tried a number of things, always starting with a List Rows action on the Dataverse table. From there, I feel like the thing to do is to do a Select action where I map OrderNumber to OrderNumber from the List Rows. I believe that creates an array of the order numbers.
I'm not sure if I'm on the right track, but how can I efficiently filter the original array where the Order Number does not exist in the Dataverse table?
Edit: Here's a sample item in the output of my current filter array:
This might help if you are able to use javascript.
// where output equals your data
const records = JSON.parse( output );
// we will create new array of filtered data
let newData = [];
// loop array searching for matching criteria
for (let n = 0; n < records.length; n++; ) {
// replace 123456 with search criteria
if(records[n]["Order Number"] != "123456") {
newData.push(records[n]);
}
// once you reach the end
if(n == records.length-1) {
// stringify object (may not be required)
let fileteredData = JSON.stringify(newData);
/* open filteredData with program */
}
}
I have a set of data in a Google spreadsheet in two columns. One column is a list of article titles and the other is the ID of a hotel that is in that article. Call it list1.
Example data
I would like returned a new list with article titles in one column, and an array of the hotel IDs in that article in the other column. Call it list2.
Example data
There are thousands of lines that this needs to be done for, and so my hope was to use Google Apps Script to help perform this task. My original thinking was to
Create column 1 of list2 which has the unique article titles (no script here, just the G-sheets =unique() formula.
Iterate through the titles in list2, looking for a match in first column of the list1
If there is a match:
retrieve its corresponding value in column 2
push it to an empty array in column two of list2
move onto next row in list1
if no longer a match, loop back to step 2.
I've written the following code. I am currently getting a type error (TypeError: Cannot read property '0' of undefined (line 13, file "Code")), however, I wanted to ask whether this is even a valid approach to the problem?
function getHotelIds() {
var outputSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('list2');
var lastRow = outputSheet.getLastRow();
var data = outputSheet.getRange(2,1,lastRow,2).getValues();
var workingSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('list1');
var lastActiveRow = workingSheet.getLastRow();
var itemIDS = [];
for (var i=1; i<=data.length; i++) {
var currentArticle = data[i][0];
var lookupArticle = workingSheet[i][0];
if (currentArticle === lookupArticle) {
var tempValue = [workingSheet[i][1]];
itemIDS.push(tempValue);
}
}
}
Use a simple google sheets formula:
You can use a very simple formula to achieve your goal instead of using long and complicated scripts.
Use =unique(list1!A2:A) in cell A2 of list2 sheet to get the unique hotels.
and then use this formula to all the unique hotels by dragging it down in column B.
=JOIN(",",filter(list1!B:B,list1!A:A=A2))
You got the idea right, but the logic needed some tweaking. The "undefined" error is caused by the workingSheet[i][0]. WorkingSheet is a Sheet object, not an array of data. Also, is not necessary to get the data from list2 (output), it is rather the opposite. You have to get the data from the list1 (source) sheet instead, and iterate over it.
I added a new variable, oldHotel, which will be used to compare each line with the current hotel. If it's different, it means we have reached a different Hotel and the data should be written in list2.
function getHotelIds() {
var outputSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('list2');
var outLastRow = outputSheet.getLastRow();
var workingSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('list1');
var lastActiveRow = workingSheet.getLastRow();
var sourceValues = workingSheet.getRange("A2:B" + lastActiveRow).getValues();
var itemIDS = [];
var oldHotel = sourceValues[0][0]; //first hotel of the list
for (var i = 0; i < sourceValues.length; i++) {
if (sourceValues[i][0] == oldHotel) {
itemIDS.push(sourceValues[i][1]);
/*When we reach the end of the list, the oldHotel variable will never be different. So the next if condition is needed. Otherwise it wouldn't write down the last Hotel.
*/
if (i == sourceValues.length - 1) {
outputSheet.getRange(outLastRow + 1, 1, 1, 2).setValues([
[sourceValues[i][0], itemIDS.toString()]
]);
}
} else {
outputSheet.getRange(outLastRow + 1, 1, 1, 2).setValues([
[sourceValues[i - 1][0], itemIDS.toString()]
]);
oldHotel = sourceValues[i][0]; //new Hotel will be compared
outLastRow = outputSheet.getLastRow(); //lastrow has updated
itemIDS = []; //clears the array to include the next codes
}
}
}
I also converted the itemIDS array to a String each time, so it's written down in a single cell without issues.
Make sure each column of the Sheet is set to "Plain text" from Format > Number > Plain Text
References
getRange
setValues
toString()
I am writing a script that updates a cell in a Google Sheet based on the intersection of a Row and Column. I find the row by iterating through a list of unique teacher names. When I find the name, I capture its row number in the variable "row". I then iterate through a range of column headers that are dates to find the specific date, and capture its column number as the variable "column". However, when I look at the structure of each object in my code, the "names" object appears as [[Person1], [Person2],..., [PersonX]] whereas the "dates" object appears as [[date1, date2,..., dateX]]. I can iterate through the names object just fine, but the dates object, not so much, and I suspect it is due to the structure.
I understand that the getDisplayValues returns a string and it works fine in another area of my code when I need to grab the date from a cell and name it "dateValue". But when I look for that dateValue in the "dates" object in the code below, that is where my code fails.
Here is a sample of the code:
function updateTracker(){
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var teacherName = sheet.getRange('F7').getDisplayValue();
var dateValue = sheet.getRange('N7').getDisplayValue();
var tracker = SpreadsheetApp.openById('AAAbbbCCCxxxYYYzzz111222333');
var tab = tracker.getSheetByName('Tracker');
var names = tab.getRange(1, 4, tab.getLastRow(), 1).getDisplayValues();
var dates = tab.getRange(1, 1, 1, tab.getLastColumn()).getDisplayValues();
for (var i in names) {
if (names[i][0] === teacherName) {
var row = parseInt(i+1);
}
}
for (var j in dates){
if (dates[0][j] === dateValue) {
var column = parseInt(j+1);
}
}
var cell = tab.getRange(row, column).setValue('x');
}
I get an error on that last line that getRange expects (number, number) but it getting (number, null).
Any suggestions on editing the code?
Logic:
In case of [[Person1], [Person2],..., [PersonX]], You iterate the "outer" array. There are X elements in the outer array. Each element itself is a array("inner") like [Person1] with only 1 primitive element each lime Person1.
Whereas the "dates" object appears as [[date1, date2,..., dateX]]. There is only 1 element in the outer array[date1, date2,..., dateX] and this array contains many elements like date1.
Solution:
You should iterate the inner array in the dates array:
for (var j in dates[0]){//note `[0]`
Using for...in to iterate arrays is also considered bad practice. Use for...of instead:
let column = null, j = 0;
for (const date of dates[0]){
j++;
if (date === dateValue) {
column = parseInt(j+1);//also bad to declare var in a block. Moved declaration outside
}
}
References:
What does the range method getValues() return and setValues() accept?
Why is using "for...in" for array iteration a bad idea?
for...of -MDN reference
I'm trying to place a data into a specific location in an array using array.splice(). So that I can get data from sheet1 to the main sheet in the right column.
Here's how it looks so far. (The Code actually returns correctly at Logger.log)
var header1 = data1[0]; //Header of Sheet1
var header2 = data2[0]; //Header of sheet2
var newData = new Array(44); //There are 45 columns
for (i in data1) {
if (i > 0) { //Take Row by Row Except Header of Sheet1
var row = data1[i];
if (row != "") {
for (j in data2) { //Searching Through All Rows of Sheet2
var row2 = data2[j];
if (row[0] == row2[4]) { //If Data In Column Match That Row, Proceed
//Getting the Right Index of SameName Column
for (i in header2) {
var col = header2[i];
for (j in header1) {
var col2 = header1[j];
if (col == col2) {
Logger.log(j+" "+row2[i]);
newData.splice(j,0,row2[i]);
}
}
}
}
}
}
}
It Returns Correctly 1 Line before:
Logger.log(j+" "+row2[i]);
42 Timestamp
3 Name
4 lastName
2 DoB
0 ID . .. 1 Type //All data returns correctly with the correct index (and none is null)
Here's The Issue:
Logger.log(newData);
[ID, Type, null, null, DoB, null, ...., TimeStamp, null, null]
DoB had index at 2 in previous line at Logger.log, but somehow the array has null at pos2.
Also... newData.length increases from 44 to 68
Somehow the index and data got mixed up later in the array.
Thank you in advance to all of you.
If you log your newly-instantiated array, you will see that, by default, all array elements are assigned a value of 'null'. In JavaScript, arrays are dynamic, which means their size is not pre-determined.
Assuming that for some rows the condition 'if (row[0] == row2[4])' evaluates to 'false', some indices will be skipped. Naturally, it will produce null elements in your fixed-size array.
Use array literal notation and Array.prototype.push() method to add new elements:
var newData = [];
newData.push(element);
Also, you shouldn't be using the 'for in' loop for iterating over arrays. Using it is precisely why you don't see 'null' values being logged. More details here Why is using "for...in" with array iteration a bad idea?
In Parse, I have a class called Queries. In this class I have a column that is of array type called favorites I would like to display that array in a UITableView The trouble is that the query downloads the favorites array column as one array, instead of multiple.
For example:
Row 1 has ["Bananas"] in favorites column
Row 2 has ["Apples", "Oranges"] in favorites column.
Row 3 has ["Tomatoes"] in favorites column
I would like the tableView to show:
Bananas
Apples, Oranges
Tomatoes
But now its showing:
Bananas
Apples
Oranges
var favorites : [String] = []
let query = PFQuery(className: "Queries")
query.findObjectsInBackground { (object, error) in
if object != nil && error == nil {
if let returnedObjects = object {
for objects in returnedObjects {
let getFavorites = objects["favorites"] as! [String]
self.favorites.append(contentsOf: getFavorites)
self.tableView.reloadData()
}
}
}
}
The tableView is populated like this: cell.favoritesLabel.text = favorites[indexPath.row]
Your favourites variable is a single dimension array, so you should either join values from a single row, or make it a two dimensional array and handle it appropriately.
To join values replace your append line with this one:
self.favorites.append(getFavorites.joined(separator: ", "))
First of all change your favorites array to this
var favorites: [[String]] = []
And change this self.favorites.append(contentsOf: getFavorites)
To this self.favorites.append(getFavorites)
The mistake is that you are appending string to an array of strings ignoring that they came in an array in the first place,
now after that you can reduce your items to one string to set it in the cell
like this
cell.favoritesLabel.text = (favorites[indexPath.row])[1..<array.count].reduce(array[0]) { $0 + ", " + $1 }
Although not strictly relevant to your question, I thought I would mention that the Parse iOS SDK does provide a set of prebuilt UI elements one of which is PFQueryTableViewController.
If you haven't already, it may be worth taking a look at the PFQueryTableViewController section in the docs to see if that would simplify your implementation in this case.