finding unique names before saving in c# and sql server - unique

i have to handle unique names and save it in db like -
If name already exists, find the smallest number you can append to the name to save it as a unique name.
For example:
If username Scott already exists, save as Scott(1). If Scott(1) already exists, save as Scott(2). Etc.
i am using c# and sql server 2010
any great ideas ?

figured that out - but appreciate improvements
var seprator = "scott";
var list = new List<string>();
list.Add("scott");
list.Add("scott(1)");
list.Add("scott Alex");
list.Add("scott (4)");
list.Add("scott(xxx)");
list.Add("scott(250)");
list.Add("scott(12s)");
list.Add("scott(123)x");
list.Add("Scott caps");
list.Add("Alex Scott caps");
list.Add("xxxscottmmm");
var numberList = new List<int>();
foreach (var v in list)
{
var parts = Regex.Split(v, seprator, RegexOptions.IgnoreCase);
if (parts.Length > 1) //(1) Alex (4) (xxx) (250) (12s) (123)x caps caps
{
var secondPart = parts[1].Trim();
if (secondPart.StartsWith("(") && secondPart.EndsWith(")")) // (1) (4) (xxx) (250) (12s)
{
var valuebetweenbraces = secondPart.Substring(1, secondPart.Length - 2); //1 4 xxx 250 12s
int number;
var isNumber = int.TryParse(valuebetweenbraces, out number);
if (isNumber)
{
numberList.Add(number);
}
}
}
}
int maxValue = 0;
if (numberList.Count > 0)
maxValue = numberList.Max() + 1;
else
maxValue = maxValue + 1;
Response.Write(seprator + "(" + maxValue + ")");

Related

How to deal with duplicates in google sheets script?

So in the project I want to do I have a google sheet with timestamps and names next to those timestamps in the spreadsheet. I am having trouble accounting for duplicates and giving the name multiple timestamps in another google sheet.
for(var i = 0; i < length; i++){//for loop 1
if(currentCell.isBlank()){//current cell is blank
daySheet.getRange(i+10, 2).setValue(fullName);//set name to first cell
daySheet.getRange(i+10,3).setValue(pI);
daySheet.getRange(i+10,day+3).setValue(1);
}else if(counter > 1 ){//the index of the duplicate in the sheet month
//if counter is > 1 then write duplicates
for(var t = 1; t <= sheetLength ; t++){//loop through sign in sheet
//current index i
if(signInLN == signInSheet.getRange(t+1,3).getValue()){
//if there is a match
daySheet.getRange(t+10,day+3).setValue(1);
//day is equal to the day I spliced from the timestamp
//at this point I am confused on how to get the second date that has the same
//name and add to the row with the original name.
//when i splice the timestamp based on the row of index i, with duplicates I get
//the day number from the first instance where the name is read
}
}
}//for loop 1
How can I get this to work with duplicates so I can account for the dates but make sure that if there are
any duplicates they will be added to the row of the original name
Google Sheet EX:
12/10/2020 test1
12/11/202 test2
12/15/2020 test1
Should be something like this:
name 10 11 12 13 14 15 16
test1 1 1
test2 1
//the one is to identify that the date is when the user signed in on the sheets.
Sample Spreadsheet:
Code snippet done with Apps Script, adapt it to your needs.
use Logger.log() in case you don't understand parts of code
It is done mainly with functional JavaScript
function main(){
var inputRange = "A2:B";
var sheet = SpreadsheetApp.getActive().getSheets()[0]
var input = sheet.getRange(inputRange).getValues(); //Read data into array
var minDate, maxDate;
var presentDates = input.map(function(row) {return row[0];}); //Turns input into an array of only the element 0 (the date)
minDate = presentDates.reduce(function(a,b) { return a<b?a:b}); //For each value, if its the smallest: keep; otherwise: skip;
maxDate = presentDates.reduce(function(a,b) { return a>b?a:b}); //Same as above, but largest.
var dates = [];
for (var currentDate = minDate; currentDate <= maxDate; currentDate.setDate(currentDate.getDate()+1)) {
dates.push(getFormattedDate(currentDate)); //Insert each unique date from minDate to maxDate (to leave no gaps)
}
var uniqueNames = input.map(function(row) {return row[1];}) //Turns input into an array of only the element at 1 (the names)
.filter(function (value, index, self) {return self.indexOf(value) === index;}); //Removes duplicates from the array (Remove the element if the first appearence of it on the array is not the current element's index)
var output = {}; //Temporary dictionary for easier counting later on.
for (var i=0; i< dates.length; i++) {
var dateKey = dates[i];
for (var userIndex = 0; userIndex <= uniqueNames.length; userIndex++) {
var mapKey = uniqueNames[userIndex]+dateKey; //Match each name with each date
input.map(function(row) {return row[1]+getFormattedDate(row[0])}) //Translate input into name + date (for easier filtering)
.filter(function (row) {return row === mapKey}) //Grab all instances where the same date as dateKey is present for the current name
.forEach(function(row){output[mapKey] = (output[mapKey]||0) + 1;}); //Count them.
}
}
var toInsert = []; //Array that will be outputted into sheets
var firstLine = ['names X Dates'].concat(dates); //Initialize with header (first element is hard-coded)
toInsert.push(firstLine); //Insert header line into output.
uniqueNames.forEach(function(name) {
var newLine = [name];
for (var i=0; i< dates.length; i++) { //For each name + date combination, insert the value from the output dictionary.
var currentDate = dates[i];
newLine.push(output[name+currentDate]||0);
}
toInsert.push(newLine); //Insert into the output.
});
sheet.getRange(1, 5, toInsert.length, toInsert[0].length).setValues(toInsert); //Write the output to the sheet
}
// Returns a date in the format MM/dd/YYYY
function getFormattedDate(date) {
var year = date.getFullYear();
var month = (1 + date.getMonth()).toString();
month = month.length > 1 ? month : '0' + month;
var day = date.getDate().toString();
day = day.length > 1 ? day : '0' + day;
return month + '/' + day + '/' + year;
}
Run script results:

Automatically generate a unique sequential ID in Google Sheets

In Google Sheets, I have a spreadsheet called Events/Incidents which staff from various branches populate. I want Column B to automatically generate a unique ID based on the year in column A and the previously populated event. Given that there could be several events on a particular day, rows in column A could have duplicate dates.
The following is an example of what I am looking for in column B:
There can be no duplicates. Would really appreciate some help with either code or formula.
There are my thoughts https://github.com/contributorpw/google-apps-script-snippets/blob/master/snippets/spreadsheet_autoid/autoid.js
The main function gets a sheet and makes the magic
/**
*
* #param {GoogleAppsScript.Spreadsheet.Sheet} sheet
*/
function autoid_(sheet) {
var data = sheet.getDataRange().getValues();
if (data.length < 2) return;
var indexId = data[0].indexOf('ID');
var indexDate = data[0].indexOf('DATE');
if (indexId < 0 || indexDate < 0) return;
var id = data.reduce(
function(p, row) {
var year =
row[indexDate] && row[indexDate].getTime
? row[indexDate].getFullYear() % 100
: '-';
if (!Object.prototype.hasOwnProperty.call(p.indexByGroup, year)) {
p.indexByGroup[year] = [];
}
var match = ('' + row[indexId]).match(/(\d+)-(\d+)/);
var idVal = row[indexId];
if (match && match.length > 1) {
idVal = match[2];
p.indexByGroup[year].push(+idVal);
}
p.ids.push(idVal);
p.years.push(year);
return p;
},
{ indexByGroup: {}, ids: [], years: [] }
);
// Logger.log(JSON.stringify(id, null, ' '));
var newId = data
.map(function(row, i) {
if (row[indexId] !== '') return [row[indexId]];
if (isNumeric(id.years[i])) {
var lastId = Math.max.apply(
null,
id.indexByGroup[id.years[i]].filter(function(e) {
return isNumeric(e);
})
);
lastId = lastId === -Infinity ? 1 : lastId + 1;
id.indexByGroup[id.years[i]].push(lastId);
return [
Utilities.formatString(
'%s-%s',
id.years[i],
('000000000' + lastId).slice(-3)
)
];
}
return [''];
})
.slice(1);
sheet.getRange(2, indexId + 1, newId.length).setValues(newId);
}
I think it can be simplified in the feature.
There is an easier way to generate unique values that works for me, pick a #, then do +1. Ctrl C, then Ctrl shift V to paste back and remove the formula. Now you are left with thousands of unique IDs.
This is a manual solution but you can do an entire database in a matter of seconds every once in a while.

Random generate three integer values and check if they are unique

First, I am generating random integer values to get some values to check.
var A1, B2, C3:int;
A1 = Math.random() * 100 + 1;
B2 = Math.random() * 100 + 1;
C3 = Math.random() * 100 + 1;
Then I want to check if all the variables are unique from each other.
if (!(A1 == B2 || A1 == C3 || B2 == C3)){
unique = true;
}else{ // Not unique
}
If the variables are not unique to each other, I want to keep only the value for A1, and then change the two other variables B2 and C3 and then again check if they are unique.
}else{ // Not unique
if (unique = false){
do{
B2 = Math.random() * A1 + 1;
C3 = Math.random() * A1 + 1;
if (!(A1 == B2 || A1 == C3 || B2 == C3)){
unique = true;
}while (unique = true)
}
trace("Not unique");
}
My problem is that I cannot get three unique values, and any help on how I can solve this is highly appreciated.
This is a case where instead of asking to resolve the problem at hand you should probably have started by explaining what you are trying to do and what's the best way to achieve it. Since you have been posting a few times already my guess is that you are trying to extract 3 unique int from a range of 0 to 100. If that's the case then you are trying to create a complex and inefficient way to do it which is interesting by itself but is far from the point. The solution is to simply generate an array of int from 0 to 100 and then extract 3 of them randomly. In that case they will always be unique and always from 0 to 100.
var intRange:Array = [];
for(var i:int = 0; i < 100; i++)
{
intRange.push(i);
}
var index:int = Math.flor(Math.random() * intRange.length);
var a:int = intRange[index];
intRange.splice(index, 1);
index = Math.flor(Math.random() * intRange.length);
var b:int = intRange[index];
intRange.splice(index, 1);
index = Math.flor(Math.random() * intRange.length);
var c:int = intRange[index];
intRange.splice(index, 1);
//3 unique int from 0 to 100 range
Your problem is the wrong code here:
if (unique = false) { // must be: if (unique == false)
do {
...
} while (unique = true) // must be: while(unique == false)
}
also it can be reduced to
while(!unique) {
...
}
Also, there you are taking random from A1, not 100. Just too many errors. The proper code should be:
var a:int, b:int, c:int; // also, why would you call variables A1, B2, C3???
a = Math.random() * 100 + 1;
do {
b = Math.random() * 100 + 1;
while(b == a);
do {
c = Math.random() * 100 + 1;
} while(c == a || c == b);
// here you have unique
Now, the answer given by BotMaster is correct and robust but it involves filling an array and splicing it which is not always ok, especially if random range is significantly more than 100 and we need only three values from it.

AS3-Flash cs6 How to make numbers have a comma?

I am making a game that when you click on the Monster your score gets +1. But when your score goes over 1000 I would like it like this 1,000 rather than 1000. I am not sure how to do this as I have not learnt much action script. I have embed number and punctuation into the font. Here is my code so far:
var score:Number = 0;
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
Monster.addEventListener(TouchEvent.TOUCH_TAP, fl_TapHandler);
function fl_TapHandler(event:TouchEvent):void
{
score = score + 1;
Taps_txt.text = (score).toString();
}
Help will greatly appreciated.
You can do like that:
function affScore(n:Number, d:int):String {
return n.toFixed(d).replace(/(\d)(?=(\d{3})+\b)/g,'$1,');
}
trace(affScore(12345678, 0)); // 12,345,678
This may not be the most elegant approach, but I wrote a function that will return the string formatted with commas;
public function formatNum(str:String):String {
var strArray:Array = str.split("");
if (strArray.length >= 4) {
var count:uint = 0;
for (var i:uint = strArray.length; i > 0; i--) {
if (count == 3) {
strArray.splice(i, 0, ",");
count = 0;
}
count++;
}
return strArray.join("");
}
else {
return str;
}
}
I tested it on some pretty large numbers, and it seems to work just fine. There's no upper limit on the size of the number, so;
trace (formatNum("10000000000000000000"));
Will output:
10,000,000,000,000,000,000
So in your example, you could use it thusly;
Taps_txt.text = formatNum(String(score));
(This is casting the type implicitly rather than explicitly using toString();, but either method is fine. Casting just looks a little neater in function calls)
Use the NumberFormatter class:
import flash.globalization.NumberFormatter;
var nf:NumberFormatter = new NumberFormatter("en_US");
var numberString:String = nf.formatNumber(1234567.89);
trace("Formatted Number:" + numberString);
// Formatted Number:1,234,567.89
To show the score with comma, you can do like this : ( comments are inside the code )
var score:Number = 0;
var score_str:String;
var score_str_len:int;
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
Monster.addEventListener(TouchEvent.TOUCH_TAP, fl_TapHandler);
function fl_TapHandler(event:TouchEvent):void
{
score = score + 1;
score_str = score.toString();
score_str_len = score_str.length;
// here you can use score > 999 instead of score_str_len > 3
Taps_txt.text =
score_str_len > 3
// example : 1780
// score_str_len = 4
// score_str.substr(0, 4 - 3) = 1 : get thousands
// score_str.substr(4 - 3) = 780 : get the rest of our number : hundreds, tens and units
// => 1 + ',' + 780 = 1,780 : concatenate thousands + comma + (hundreds, tens and units)
? score_str.substr(0, score_str_len-3) + ',' + score_str.substr(score_str_len-3)
: score_str
;
// gives :
// score == 300 => 300
// score == 1285 => 1,285
// score == 87903 => 87,903
}
EDIT :
To support numbers greater than 999.999, you can do like this :
function fl_TapHandler(event:MouseEvent):void
{
score = score + 1;
score_str = score.toString();
Taps_txt.text = add_commas(score_str);
}
function add_commas(nb_str:String):String {
var tmp_str:String = '';
nb_str = nb_str.split('').reverse().join('');
for(var i = 0; i < nb_str.length; i++){
if(i > 0 && i % 3 == 0) tmp_str += ',';
tmp_str += nb_str.charAt(i);
}
return tmp_str.split('').reverse().join('');
/*
gives :
1234 => 1,234
12345 => 12,345
123456 => 123,456
1234567 => 1,234,567
12345678 => 12,345,678
123456789 => 123,456,789
1234567890 => 1,234,567,890
*/
}
Hope that can help you.

GML Storing User Input

So I have been working on a program that ask the user to input a values and when the user exits the code by entering -99 its suppose to return the total Value of all the numbers and the average but I'm stumped My values keep getting overided by the previous one... here is my code
{
var user_Input;<br>
var output_msg;<br>
var count;<br>
var highest;<br>
var value;<br>
var total;<br>
count = 0;
do
{
user_Input = get_integer("Enter a number To add To the List(Enter -99 to leave)",-99);
if (user_Input == (-99)){
continue}
count += 1;
value = 0;
value = value + user_Input;
average = value/count;
}
until(user_Input == (-99)){
count -=1;
user_Input = user_Input + 99;
output_msg=("#Numbers Entered: " + string(count) + "##Total value of numbers: " + string(highest) + "## Average:" + string(average));`
}
show_message(output_msg);
}
How Do I make it so it doesn't override the previous one?
This is because you are setting value equal to 0 every time the while loop is executed. Try setting
value = 0;
before you start the do until loop. Perhaps right after
count = 0;
like this:
count = 0;
value = 0;
do{
user_Input = get_integer("Enter a number To add To the List(Enter -99 to leave)",-99);
if (user_Input == (-99)){continue}
count += 1;
value = value + user_Input;
average = value/count;
}