removing the double quotes from list of elements - coldfusion

i have a list and where my list is coming as some elements being as double quotes with no value inside it
like:
ID,"",name,"",email,date,description,"",timelogged
i am trying to get a list which has
ID,name,email,date,description,timelogged
i tried converting the listoarray and then back to list to remove empty list elements, but it is not doing so.
is there any regex i can use to do it.

<cfscript>
list = 'ID,"",name,"",email,date,description,"",timelogged';
aItems = listToArray(list);
aItems = aItems.filter(function(value){
return value != '""';
});
newList = arrayToList(aItems);
writeOutput("Starting list: " & list & "<br />");
writeOutput("Filtered list: " & newList & "<br />");
</cfscript>

If you just want to remove all of the empty string elements, then just remove all of the empty string elements.
<cfset x = 'ID,"",name,"",email,date,description,"",timelogged'>
<cfset x = rereplace(x, "#chr(44)##chr(34)##chr(34)#", "", "all")>
<cfoutput>#x#</cfoutput>
Output
ID,name,email,date,description,timelogged

Related

Is there a way this can be done in list comprehension

I am trying to do this using list comprehension. I am using a subset of python 2.7 that does not allow the use of the command any or all
string_list1 = ['James Dean', 'Mr. James Dean', 'Jon Sparrow', 'Timothy Hook', 'Captain Jon Sparrow']
string_list2 = []
# Get elements that are a substring of other elements
for str1 in string_list1:
for str2 in string_list1:
if str1 in str2 and str1 != str2:
string_list2.append(str1)
print('Substrings: ', string_list2)
# remove element if another element is within it
for str2 in string_list2:
for str1 in string_list1:
if str2 in str1 and str2 != str1:
string_list1.remove(str1)
print('Desired: ', string_list1) # all elements that are unique
The result should be ['James Dean', 'Jon Sparrow', 'Timothy Hook'] basically the substrings and non substring elements
You could apply the same algorithm with list comprehension like this:
lst = ['James Dean', 'Mr. James Dean', 'Jon Sparrow', 'Timothy Hook', 'Captain Jon Sparrow']
res = [primitive for primitive in lst
if primitive not in (superstr for superstr in lst
if [substr for substr in lst if substr in superstr and substr != superstr]
)
]
print(res)
But an interpreter will not see that the inner expression (superstr ...) has to be evaluated only once, not for every iteration of the outer loop. So I would prefer to do this in two steps:
lst = ['James Dean', 'Mr. James Dean', 'Jon Sparrow', 'Timothy Hook', 'Captain Jon Sparrow']
exclude = [superstr for superstr in lst
if [substr for substr in lst if substr in superstr and substr != superstr]
]
res = [primitive for primitive in lst if primitive not in exclude]
print(res)

Sum up dynamic fields in list

I have a list like:
<cfset list ="group 1:1; group 2:4; group a:7; group 1:3; group a:1;">
What I want to do is count (sum up) how many people are in group 1, group 2, group a, etc.. Now these fields are dynamic, so I don't know the exact name of the groups.
So the end result in this example is:
group 1: 4
group 2: 4
group a: 8
So the list is just an example, in reality it's much bigger with more groups (dynamic names). I'm using Coldfusion/Lucee. Can someone help me with this?
Just one of numerous of possible alternative ways of doing this. Starting from using a query instead of a list as the starting value.
What I am doing is to loop the list with ; as delimiter and adding the values to a structure. I later use that structure to loop and list the final total.
<cfset list ="group 1:1; group 2:4; group a:7; group 1:3; group a:1;">
<cfset totalStruct = {}>
<cfloop list="#list#" item="group" delimiters=';'>
<cfset groupName = listFirst(group, ':')>
<cfset groupNameKey = replace(groupName, ' ', '', 'all')>
<cfset groupValue = val(listLast(group, ':'))>
<cfif !structKeyExists(totalStruct, groupNameKey)>
<cfset totalStruct[groupNameKey] = {name:groupName, total=groupValue}>
<cfelse>
<cfset totalStruct[groupNameKey].total += groupValue>
</cfif>
</cfloop>
<cfoutput>
<ul>
<cfloop collection="#totalStruct#" item="group">
<li>#totalStruct[group].name# : #totalStruct[group].total#</li>
</cfloop>
</ul>
</cfoutput>
DEMO
Another alternative is to use the map and/or reduce closure functions to parse your list.
NOTE 1: I generally find cfscript to be much easier for most things for parsing text or "looping".
NOTE 2: I'm not a huge fan of loops, especially around large text values. Closure functions will likely be much more performant.
<cfset lst ="group 1:1; group 2:4; group a:7; group 1:3; group a:1;">
First, with a map() inside of a function:
<cfscript>
public Struct function parseLst (required String lst) {
var retval = {} ; //// Default return variable.
//// https://docs.lucee.org/reference/functions/listmap.html
arguments.lst.listmap(
function(el) {
var k = el.listFirst(":").ltrim() ; /// Get the "key" and strip extra leading space.
var v = el.listLast(":") ; /// Get the "value".
var p = retval["#k#"]?:0 ; /// Use Elvis to default to 0 if no struct Key exists.
retval["#k#"] = v + p ; /// Set the value of the key. NOTE: A struck key with the same name will generally overwrite itself. We want to add it.
}
,";" /// Specify the delimiter of the list.
) ;
return retval ;
}
writeDump(parseLst(lst));
</cfscript>
Then with a reduce() without being inside a function.
<cfscript>
//// https://docs.lucee.org/reference/functions/listreduce.html
r = listReduce(lst,
function(prev,nxt){
k = nxt.listFirst(":").ltrim() ; /// Get the "key" and strip extra leading space.
/// To shorten it, I just skipped setting the value beforehand and just did it while setting the struct value. Same method as above.
prev["#k#"] = (nxt.listLast(":"))+(prev["#k#"]?:0) ;
return prev ;
}
,
{} // Initial value
,";" // Delimiter
) ;
writedump(r) ;
</cfscript>
Both could (and probably should) be inside a function, and then you could just send your list variable to it.
And if possible, it might be a lot easier to fix the original list to be simpler to work with.
https://trycf.com/gist/dda51d88504a625fce5548142d73edb3/lucee5?theme=monokai
=======================================================
EDIT:
An alternative to using listFirst/Last() functions would be to just convert the "list" to an array and then use those pieces to get your "key" and "value".
<cfscript>
//// https://docs.lucee.org/reference/functions/listreduce.html
s = listReduce(lst,
function(prev,nxt){
var elem = nxt.listToArray(":") ;
prev["#elem[1].ltrim()#"] = elem[2] + (prev["#elem[1].ltrim()#"]?:0) ;
return prev ;
}
,
{} // Initial value
,";" // Delimiter
) ;
writedump(s) ;
</cfscript>

Replace occurence in a String in Kotlin

I have two list of Strings. Now I want to replace every occurence of a word in the first list at index i with a word in the second list at index i of a sentence.
So if I have
list a=("am","I","my")
and
list b=("are","You","your")
I want the sentence "I am an amateur"
to become "You are an amateur"
What is cleanest way to do that in Kotlin (without for loop)?
First split the string to a list of its words and then map each word if it exists in list a to the corresponding word in list b. Finally rejoin the string:
val a= listOf("am","I","my")
val b= listOf("are","You","your")
val str = "I am an amateur"
val new = str
.split("\\s+".toRegex())
.map { val i = a.indexOf(it); if (i < 0) it else b[i] }
.joinToString(" ")
Another way of doing the same thing is:
var new = " $str "
a.forEachIndexed { i, s -> new = new.replace(" $s ", " ${b[i]} ") }
new = new.trim()
although this is closer to a for loop.
I assume there is no punctuation, all whitespaces are spaces and so on.
val m = a.zip(b).toMap()
return s.split(' ').joinToString(" ") { m[it] ?: it }
First you create a map m for more efficient... mapping. Then
Split the string to get a list of words
Map all words: if m contains the word, then return the value (i.e. the replacement), otherwise return the original word (since we shouldn't replace it).
Join all words, separate them by spaces.
You can use the regular expression \b\w+\b to match words in a sentence and then call replace function with the lambda that provides a replacement string for each match:
val input = "I am an amateur, alas."
val wordsToReplace = listOf("I", "am", "my")
val wordsReplaceWith = listOf("You", "are", "your")
val wordRegex = """\b\w+\b""".toRegex()
val result = wordRegex.replace(input) { match ->
val wordIndex = wordsToReplace.indexOf(match.value)
if (wordIndex >= 0) wordsReplaceWith[wordIndex] else match.value
}
println(result)
If there are a lot of word in your lists, it makes sense to build a map of them to speed up searches:
val replaceMap = (wordsToReplace zip wordsReplaceWith).toMap()
val result = wordRegex.replace(input) { match ->
replaceMap[match.value] ?: match.value
}
I think the simplest way is to create a set of regex you want and replace the string by iteration. Let's say you want to replace the word "am", your regex will be "\bam\b". You can use "(?i)\bam\b" if you want it not to be case sensitive. To make "I am an amateur" to "You are an amateur"
val replacements = setOf("\\bam\\b" to "are",
"\\bI\\b" to "You",
"\\bmy\\b" to "your")
replacements.forEach {
str = str.replace(Regex(it.first), it.second)
}

ViM: how to put string from input dialog in a list

VIM: Does anyone know how to put a string from an input dialog in a list?
p.e.:
the string "3,5,12,15"
to:
list item[1] = 3
list item[2] = 5
list item[3] = 12
etc.
and how can I know how many list items there are?
From :h E714
:let l = len(list) " number of items in list
:let list = split("a b c") " create list from items in a string
In your case,
let string = "3,5,7,19"
let list = split(string, ",")
echo len(list)
Use split, len and empty functions:
let list=split(string, ',')
let list_length=len(list)
" If all you want is to check whether list is empty:
if empty(list)
throw "You must provide at least one value"
endif
Note that if you want to get a list of numbers out of the string, you will have to use map to transform list elements into numbers:
let list=map(split(string, ','), '+v:val')
Most of time you can expect strings be transformed into numbers, but sometimes such transformation is not done.

Classic ASP comparison of comma separated lists

I have two comma separated lists:-
36,189,47,183,65,50
65,50,189,47
The question is how to compare the two in classic ASP in order to identify and return any values that exist in list 1 but that don't exist in list 2 bearing in mind that associative arrays aren't available.
E.g., in the above example I would need the return value to be 36,183
Thanks
Something like this (untested):
str1 = "36,189,47,183,65,50"
str2 = "65,50,189,47"
arr1 = Split(str1, ",")
arr2 = Split(str2, ",")
for i = 0 to UBound(arr1)
found = false
for j = 0 to UBound(arr2)
if arr1(i) = arr2(j) then
found = true
end if
next
if found = false then
Response.Write(arr1(i))
end if
next
In order to solve this with regular expression you can use lookaheads (both positive and negative) and references, for example:
(zyx:~) % echo '36,189,47,183,65,50;65,50,189,47' | grep -oP '((?>(?<![^,;])[^,;]+))(?=.*;)(?!.*;(|.*,)\1(?=,|$))'
36
183
Other variant (works in PCRE but not in perl):
(zyx:~) % echo '36,189,47,183,65,50' | grep -oP '((?!(?<=,|^)65|50|189|47(?=,|$))(?<=,|^)[^,]+(?=,|$))'
36
183
Have no idea whether any of these works in asp.
VBScript has associative arrays in the form of the Dictionary object.
Dim list1, list2
list1 = "36,189,47,183,65,50"
list2 = "65,50,189,47"
Dim arr1, arr2
arr1 = Split(list1, ",")
arr2 = Split(list2, ",")
' oDict will hold values from list1
Dim oDict, i
Set oDict = Server.CreateObject("Scripting.Dictionary")
For i = 0 To UBound(arr1)
oDict(arr1(i)) = 1
Next
' Now loop through list2 and remove matching items from list1
For i = 0 To UBound(arr2)
If oDict.Exists(arr2(i)) Then
oDict.Remove arr2(i)
End If
Next
Response.Write Join(oDict.Keys, ",") ' should be "36,183"