Is there a way to change dateFormat with java 8 stream? - list

I want to change date format from "dd/mm/yyyy" to "yyyy/mm/dd" with one line in java8 stream
List<String[]> date = new ArrayList<>();
String[] a= {"12/2/2018","a1","a2"};
String[] b= {"13/3/2018","b1","b2"};
String[] c= {"14/4/2018","c1","c2"};
date.add(a)`
date.add(b);
date.add(c);
I expect the output is
{{"2018/2/12","a1","a2"},{"2018/2/13","b1","b2"},{"2018/2/14","c1","c2"}}

I hope you mean yyyy/MM/dd coz m is for minutes and M for month...
consider a Map from the stream API
public static void main(String[] args) {
List<String[]> date = new ArrayList<>();
String[] a= {"12/2/2018","a1","a2"};
String[] b= {"13/3/2018","b1","b2"};
String[] c= {"14/4/2018","c1","c2"};
date.add(a);
date.add(b);
date.add(c);
List<String[]> even = date.stream().map(
s -> {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/yyyy");
LocalDate localDate = LocalDate.parse(s[0], formatter);
DateTimeFormatter formatterNew = DateTimeFormatter.ofPattern("yyyy/MM/dd");
return new String[]{formatterNew.format(localDate), s[1],s[2]};
}
).collect(Collectors.toList());
even.forEach(x-> System.out.println(Arrays.toString(x)));
}
that will print out
[2018/02/12, a1, a2]
[2018/03/13, b1, b2]
[2018/04/14, c1, c2]

You can not do this without iterating over all items.
For your simple case dd/mm/yyyy to yyyy/mm/dd you can just use this:
date.forEach(i -> {
String[] parts = i[0].split("/");
i[0] = parts[2] + "/" + parts[1] + "/" + parts[0];
});
Using java time api you can use this:
DateTimeFormatter toFormat = DateTimeFormatter.ofPattern("yyyy/M/d");
DateTimeFormatter fromFormat = DateTimeFormatter.ofPattern("d/M/yyyy");
date.forEach(i -> i[0] = LocalDate.parse(i[0], fromFormat).format(toFormat));

You can do this by using java 8 streams, but not in one line. Use two date patterns one for input and other for output
DateTimeFormatter inFormat = DateTimeFormatter.ofPattern("dd/M/yyyy");
DateTimeFormatter outFormat = DateTimeFormatter.ofPattern("yyyy/M/dd");
List<String[]> date = new ArrayList<>();
String[] a= {"12/2/2018","a1","a2"};
String[] b= {"13/3/2018","b1","b2"};
String[] c= {"14/4/2018","c1","c2"};
date.add(a);
date.add(b);
date.add(c);
//Since it is String array need lambda expression to update and return
List<String[]> result = date.stream().map(arr->{
arr[0]=LocalDate.parse(arr[0],inFormat).format(outFormat);
return arr;
}).collect(Collectors.toList());

Why use a stream?
DateTimeFormatter originalFormatter = DateTimeFormatter.ofPattern("d/M/u");
DateTimeFormatter wantedFormatter = DateTimeFormatter.ofPattern("u/M/d");
date.forEach(arr -> {
LocalDate ld = LocalDate.parse(arr[0], originalFormatter);
arr[0] = ld.format(wantedFormatter);
});
To inspect the result:
date.forEach(arr -> System.out.println(Arrays.toString(arr)));
Output:
[2018/2/12, a1, a2]
[2018/3/13, b1, b2]
[2018/4/14, c1, c2]
My code (as well as the code in some of the other answers) modifies your original arrays. Please decide if this is OK. If it is, you shouldn’t really use a stream since they are supposed to be free from side-effects. If you do need the original arrays to remain untouched, a stream is fine (using the same formatters as before):
List<String[]> newDateList = date.stream()
.map(arr -> {
LocalDate ld = LocalDate.parse(arr[0], originalFormatter);
String[] newArr = Arrays.copyOf(arr, arr.length);
newArr[0] = ld.format(wantedFormatter);
return newArr;
})
.collect(Collectors.toList());
newDateList.forEach(arr -> System.out.println(Arrays.toString(arr)));
Output is the same as before.

Related

How to emulate the formula Proper on AppScript for a specific column?

I found the following code to emulate the proper formula, but it has a wrong ( maybe outdated) syntax, and as far as i understood, it should applies to all columns of a given sheet.
function PROPER_CASE(str) {
if (typeof str != "string")
throw `Expected string but got a ${typeof str} value.`;
str = str.toLowerCase();
var arr = str.split(/.-:?—/ );
return arr.reduce(function(val, current) {
return val += (current.charAt(0).toUpperCase() + current.slice(1));
}, "");
}
Here's an example of the input :
A
B
C
D
ColumnA
ColumnB
ColumnC
ColumnD
EXCEL ACTION LIMIMTED (毅添有限公司)
207/2018
n/a
without-proper
Hang Wo Holdings
205/2015
35/2020
without-proper
central southwood limited
308/2019
n/a
without-proper
This would be the desired output:
ColumnA ColumnB ColumnC COlumnD
Excel Action Limited (毅添有限公司) 207/2018 n/a without-proper
Hang Wo Holdings 205/2015 35/2020 without-proper
Central Southwood Limited 308/2019 n/a without-proper
And this is the error output of that function :
Erro
Expected string but got a undefined value.
PROPER_CASE # macros.gs:115
This is the only way I can see of reproducing you results. I don't see how to avoid captalizing the first letter of the last two columns with avoiding them:
function lfunko() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");
if (sh.getLastRow() > 4) {
sh.getRange(6, 1, sh.getLastRow() - 5, sh.getLastColumn()).clearContent();
SpreadsheetApp.flush();
}
const vs = sh.getDataRange().getDisplayValues().map((r, i) => {
return r.map((c, j) => {
if (i > 0 && j < 1) {
let arr = c.toString().toLowerCase().split(/.-:?-/g);
return arr.reduce((val, current) => {
//Logger.log(current)
return val += current.charAt(0).toUpperCase() + current.slice(1);
}, '');
} else {
return c;
}
});
});
Logger.log(JSON.stringify(vs))
sh.getRange(sh.getLastRow() + 2, 1, vs.length, vs[0].length).setValues(vs);
}
A
B
C
D
Data
ColumnA
ColumnB
ColumnC
ColumnD
EXCEL ACTION LIMIMTED (毅添有限公司)
207/2018
n/a
without-proper
Hang Wo Holdings
205/2015
35/2020
without-proper
central southwood limited
308/2019
n/a
without-proper
Outpput
ColumnA
ColumnB
ColumnC
ColumnD
Excel action limimted (毅添有限公司)
207/2018
n/a
without-proper
Hang wo holdings
205/2015
35/2020
without-proper
Central southwood limited
308/2019
n/a
without-proper
I have tested your code and it works fine. It does convert the input string into a proper case.
However, take note that in Google Sheets, when you get values, your data is in 2D Array or Nested Array.
So to apply this to your Spreadsheet after getting the values you will have to target the column you want to replace and loop through each string in the array. You will then have to setValues() back to the specified range to replace it in the spreadsheet.
Solution 1:
Try:
With your function, try adding this script to apply to your spreadsheet.
function setToColumn(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getRange(1,1,sheet.getLastRow()); //2ND Parameter is the column, replace if you want to edit different column
var allData = dataRange.getValues().flat();
var properData = []
allData.forEach(function(data){
properData.push([PROPER_CASE(data)])
});
dataRange.setValues(properData);
}
From:
Result:
Solution 2:
If you don't mind using different script which only needs one function you may use the script below:
function properCase() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getRange(1,1,sheet.getLastRow()); //2ND Parameter is the column, replace if you want to edit different column (1 = Column A, 2 = Column B)
var allData = dataRange.getValues().flat();
var properData = []
allData.forEach(function(data){
properData.push([data.toLowerCase().replace(/\b[a-z]/ig, function(match) {return match.toUpperCase()})]);
});
dataRange.setValues(properData);
}
Reference for Solution 2:
Apps script how to format a cell to Proper Text (Case)

How to extract date from a string in Scala

I have two Strings. The first is like this one:
{"userId":"554555454-45454-54545","start":"20141114T172252.466z","end":"20141228T172252.466z","accounts":[{"date":"20141117T172252.466z","tel":"0049999999999","dec":"a dec","user":"auser"},{"date":"20141118T172252.466z","tel":"004888888888","dec":"another dec","user":"anotheruser"}]}
the second one has the same dates but in a different format. Instead of
20141117T172252.466z
it shows
2014-11-14,17:22:52
I'm trying to extract the dates of the first String and assert that are the same with the dates from the second String. I've tried it with regular expressions but I'm getting an error Illegal repetition. How can I do this?
You can use SimpleDateFormat from java:
import java.text.SimpleDateFormat
import java.util.Date
val s1 = "{\"userId\":\"554555454-45454-54545\",\"start\":\"20141114T172252.466z\"}"
val s2 = "{\"userId\":\"554555454-45454-54545\",\"start\":\"2014-11-14,17:22:52\"}"
val i1 = s1.indexOf("start")
val i2 = s2.indexOf("start")
val str1 = s1.replace("T", "_").substring(i1+8, i1+ 23)
val str2 = s2.substring(i2+8, i2+27)
val date1: Date = new SimpleDateFormat("yyyyMMdd_hhmmss").parse(str1)
val date2: Date = new SimpleDateFormat("yyyy-MM-dd,hh:mm:ss").parse(str2)
val result = date1==date2

For loop to access dictionary

I have a NSDictionary of type String:AnyObject, and I want to have it be type String:String. How can I convert them with the same key to type string using a loop? I would think I could figure it out, but Xcode 6 sourcekit keeps crashing whenever I put in a for loop for the dictionary.
PS. I'm writing this in Swift, not Obj-C.
This way you can loop over the dictionary for objects:AnyObject:
let dict = ["A":1, "B":2, "C":3]
var string = ""
for object in dict.values {
string += "\(object)"
}
// string = "312"
If you want to loop over just the keys change to .keys as in the following:
for key in dict.keys {
string += key
}
// string = "CAB"
Finally to loop over both keys and values with a Tuple (key, object) :
let dict = ["A":1, "B":2, "C":3]
var string = ""
var sum = 0
for (key, object) in dict {
string += key
sum += object
}
// sum = 6
// string = "CAB"
Note: This works with Beta 3.

how to remove string from URL? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to strip out a url variable
I have url http://localhost/abc/detail.cfm?iId=1711471&countrysearch=3693&itemnumbersearch=&keywordsearch=&purl=%2FIGPCI%2Fthumbs%2Ecfm%3Fcountrysearch%3D3693%26itemnumbersearch%3D%26keywordsearch%3D%26x%3D78%26y%3D10&productid=1111&recordindex=1.
I want to search product details on clicking link called "next" each time i need to prepare new URL with new value of productid and recordindex.for example i have four product with respect to countryid="3693",
productid productname
1 p1
2 p2
3 p3
4 p4
when next click new URL prepare with productid=1 and recordindex=1,again click then URL is productid=2 and record id =2 and so on.
for getting URL i have used following code:
<cfset currentURL = "#CGI.SERVER_NAME#" & "#CGI.PATH_INFO#" & "#CGI.query_string#">
which give me the current url
then i prepare new url with below code:
<cfif queryString.recordset gt 0> <cfset recordindex=#recordindex#+1> <cfset newUrl=currentURL & '&productid=#queryString.poductid[recordindex]#&recordindex=#recordindex#' </cfif>
with this code that each time it's append url value with old with new one.
like:
http://localhost/abc/detail.cfm?iId=1711471&countrysearch=3693&itemnumbersearch=&keywordsearch=&purl=%2FIGPCI%2Fthumbs%2Ecfm%3Fcountrysearch%3D3693%26itemnumbersearch%3D%26keywordsearch%3D%26x%3D78%26y%3D10&productid=1111&recordindex=1&productid=2&recordindex=2
my question how to remove old &productid=1111&recordindex=1 in old URL.i tried with replace function but it replace when string are match,in my case every time product and recordindex values are change.how to remove old string using regular expression.please help me.
Thanks
You don't need regex for this. In fact, someone has already built a UDF for this.
QueryStringDeleteVar
Example:
<cfset currentURL = CGI.SERVER_NAME & CGI.PATH_INFO & queryStringDeleteVar("productid,recordindex")>
UDF code:
<cfscript>
/**
* Deletes a var from a query string.
* Idea for multiple args from Michael Stephenson (michael.stephenson#adtran.com)
*
* #param variable A variable, or a list of variables, to delete from the query string.
* #param qs Query string to modify. Defaults to CGI.QUERY_STRING.
* #return Returns a string.
* #author Nathan Dintenfass (michael.stephenson#adtran.comnathan#changemedia.com)
* #version 1.1, February 24, 2002
*/
function queryStringDeleteVar(variable){
//var to hold the final string
var string = "";
//vars for use in the loop, so we don't have to evaluate lists and arrays more than once
var ii = 1;
var thisVar = "";
var thisIndex = "";
var array = "";
//if there is a second argument, use that as the query string, otherwise default to cgi.query_string
var qs = cgi.query_string;
if(arrayLen(arguments) GT 1)
qs = arguments[2];
//put the query string into an array for easier looping
array = listToArray(qs,"&");
//now, loop over the array and rebuild the string
for(ii = 1; ii lte arrayLen(array); ii = ii + 1){
thisIndex = array[ii];
thisVar = listFirst(thisIndex,"=");
//if this is the var, edit it to the value, otherwise, just append
if(not listFind(variable,thisVar))
string = listAppend(string,thisIndex,"&");
}
//return the string
return string;
}
</cfscript>
Although, since you're looking to replace URL parameter values, QueryStringChangeVar would probably be more of what you want.
<cfscript>
/**
* Changes a var in a query string.
*
* #param name The name of the name/value pair you want to modify. (Required)
* #param value The new value for the name/value pair you want to modify. (Required)
* #param qs Query string to modify. Defaults to CGI.QUERY_STRING. (Optional)
* #return Returns a string.
* #author Nathan Dintenfass (nathan#changemedia.com)
* #version 2, September 5, 2002
*/
function QueryStringChangeVar(variable,value){
//var to hold the final string
var string = "";
//vars for use in the loop, so we don't have to evaluate lists and arrays more than once
var ii = 1;
var thisVar = "";
var thisIndex = "";
var array = "";
var changedIt = 0;
//if there is a third argument, use that as the query string, otherwise default to cgi.query_string
var qs = cgi.query_string;
if(arrayLen(arguments) GT 2)
qs = arguments[3];
//put the query string into an array for easier looping
array = listToArray(qs,"&");
//now, loop over the array and rebuild the string
for(ii = 1; ii lte arrayLen(array); ii = ii + 1){
thisIndex = array[ii];
thisVar = listFirst(thisIndex,"=");
//if this is the var, edit it to the value, otherwise, just append
if(thisVar is variable){
string = listAppend(string,thisVar & "=" & value,"&");
changedIt = 1;
}
else{
string = listAppend(string,thisIndex,"&");
}
}
//if it was not changed, add it!
if(NOT changedIt)
string = listAppend(string,variable & "=" & value,"&");
//return the string
return string;
}
</cfscript>

Add a dynamic key to an anonymous List

How can I add a dynamic key to an anonymous List such as the mydatetime below:
DateTime myDateTime = DateTime.Parse(datepickerval, ukCulture.DateTimeFormat);
var qid = (from p in db.Vw_INTERACTPEOPLE
select p
);
var AvilList = new List<object>();
var ddate = myDateTime.DayOfWeek.ToString().Substring(0, 3) + "Jul" + myDateTime.Day;
foreach (var q in qid)
{
AvilList.Add(
new
{// Availability
Name = q.Fullname,
here >>> ddate = "Some Test"
});
As adam says above there is no way to do this using Lists, however since the Slickgrid is expecting a Json return, I simply built the string in .net then returned it via the JavaScriptSerializer serializer, then in the code behind simply used eval to de-serialize back into an array.