Is there anyway I can ensure that the pool of numbers used when calling fqdn_rand will never pick the same number in a single puppet run?
I have a cronjob and I never want any of my 5 jobs to run on the same day. I've been using fqdn_rand to generate the jobs on random days but finding some servers will have jobs which run on the same days. In my mind if these numbers are removed from the possible selected numbers, I'll never get the same result.
Is there anyway I can ensure that the pool of numbers used when calling fqdn_rand will never pick the same number in a single puppet run?
You cannot ensure that multiple calls to fqdn_rand() will all return distinct values. However, you can use fqdn_rand() to perform a selection of multiple items without duplication. There are several ways you could do that, but I'm going to suggest combining it with the reduce() function to perform a (partial) shuffle of the list of options from which you want to select.
It isn't clear in the question whether you want to select from days of the week, days of the month, or something else, but for simplicity, I'll assume that you are selecting among days of the week, in the form of numbers 1 through 7:
$day_numbers = [ 1, 2, 3, 4, 5, 6, 7 ]
Although Puppet does not have general purpose looping statements such as for or while, you can iterate (among other ways) by using one of several iteration functions to process an iterable value. For example:
$selected = [ 0, 1, 2, 3, 4 ].reduce($day_numbers) |$numbers, $i| {
$selection = fqdn_rand($day_numbers.length - $i - 1, $i)
[
$numbers[0, $i], # The already selected numbers
$numbers[$selection + $i, -1], # The tail starting at the next selection
$numbers[$i, $selection] # The slice between the previous two
].flatten
}[0, 5]
That executes the lambda five times, associating successive values from 0 to 4 with variable $i. On the initial iteration, $day_numbers is associated with $numbers. On each subsequent iteration, the return value of the lambda's previous iteration is associated with $numbers.
On each iteration of the lambda, the $i elements selected in previous iterations occupy the first $i positions of $numbers. The fqdn_rand() function is used to compute the index of one of the other elements, then the tail is rotated to bring the selected element into position.
Ultimately, an array containing the first five elements of the result (those being all the selected values) is assigned to $selected.
Related
I have a string variable with comma separated numbers that I want to split into four numeric variables.
makeArr
var1a
var1b
var1c
var1d
6,8,13,10
6
8
13
10
10,11,2
10
11
2
7,1,14,3
7
1
14
3
With:
IF (CHAR.INDEX(makeArr,',') >= 1)
f12a=CHAR.SUBSTR(makeArr,1,CHAR.INDEX(makeArr,',')-1).
EXECUTE.
IF (CHAR.INDEX(makeArr,',') >= 1)
f12b=CHAR.SUBSTR(makeArr,CHAR.INDEX(makeArr,',')+1,CHAR.INDEX(makeArr,',')-1).
EXECUTE.
I always get the first variable written without any problems.
This no longer works with the second variable because it has a different length and the comma is also written here.
So I would need a split at the comma and the division of the numbers over the comma.
Since char.substr will only tell you about the location of the first occurence of the search string, you need to start the second search from a new location - AFTER the first occurence, and this gets more and more complicated as you continue. My suggestion is create a copy of your array variable, which you will cut pieces off as you proceed - so that you are only searching for the first occurence of "," every time.
First I recreate your example data to demonstrate on.
data list free/makeArr (a20).
begin data
"6,8,13,10" "10,11,2" "7,1,14,3"
end data.
Now I copy your array into a new variable #tmp. Note that I add a "," at the end so the syntax stays the same for all parts of the array. I add the "#" at the beginning of the name to make it invisible, you can remove it if you want.
It is possible to do the following calculation in steps as you started to do, but nicer to loop throug the steps (especially if this is an example for a longer array).
string f12a f12b f12c f12d #tmp (a20).
compute #tmp=concat(rtrim(makeArr),",").
do repeat nwvr=f12a f12b f12c f12d.
do IF #tmp<>"".
compute nwvr=CHAR.SUBSTR(#tmp,1,CHAR.INDEX(#tmp,',')-1).
compute #tmp=CHAR.SUBSTR(#tmp,CHAR.INDEX(#tmp,',')+1).
end if.
end repeat.
EXECUTE.
Here I found a different solution for what I think is the same problem:
https://www.ibm.com/mysupport/s/question/0D50z00006PsP3tCAF/splitting-a-string-variable-divided-by-commas-into-new-single-variables?language=es
One line of code makes the work:
spssinc trans result=var_1 to var_4 type=20/formula 're.split(", *", makeArr)'.
I have set-up a sqlite database which records some world-trading data.
I am iterating over the database and want to extract some data, which will flow into another method of that class (works - no problem).
However, iterating over the database I have two variables "row" & "l":
For Row in Database("..."):
l = self.c.fetchone()
Strangely half of the data is in the variable "row" and the other half is in "l". It took me for ever to figure out, but now I really have no idea, why this problem happens? If I iterate over a list/db for "row" - "row" should have all the data for each iteration?
I tried accessing row through "row" and "l" from different ways, from within a new loop - rewrote the loops and restructured them, but then I have too much data and over 2000 entry points??? I used fetchmany() - and made another (outside) loop to iterate over,...
for row in self.c.execute("SELECT order_number,quotaStart,valid FROM volume"):
l = self.c.fetchone()
count+=1
print(count,">>",row)
print(count,">>",l)
I expect the data to be accessible through "row" or "l" - but not one half in one variable and the other half in the other?
You are mixing up 2 different ways of accessing the results of your query. The simplest way to do it is:
for row in self.c.execute("SELECT order_number,quotaStart,valid FROM volume"):
print(count, ">>", row)
Or alternatively:
self.c.execute("SELECT order_number,quotaStart,valid FROM volume"):
while l = self.c.fetchone():
print(count, ">>", l)
I am able to capture the response using ord=All in web_reg_save_param.
case 1,
Input:12345
Response:["18/3/2017","20/2/2017","20/2/2016"].
case 2,
Input:98451
Response:["12/1/2017","01/1/2016"]
web_reg_save_param("date","LB=\"","RB=\"","ORD=ALL","LAST);
`
Captured Values are:
date_1:18/3/2017
date_2:,
date_3:20/2/2017
date_4:,
date_5:20/2/2016
Here is the task:
1) I need to fetch random date each time.
2) Date may vary depending upon the input(In case 1, 3 dates and case 2, 2 dates).
I have tried:
1) Correlating and using lr_paramarr_random() function- failed, it will fetch ',' at some point.
2) using for loop and if statement to find out odd/even position.
Using web_reg_save_param() function like you did will, of course, fetch a comma(',') since it is situated between two quote symbols(' " ').
You can use web_reg_save_param_regexp() function with the following regular expression:
"(\d{2}\/\d\/\d{4})"
Set the parameters: "Ordinal=All", "Group=1".
This function will extract the dates and store them into an array.
This time lr_paramarr_random() should return correct results because now your array contains nothing but dates.
I collect data into an excel sheet through a labview program, the data is collected continuously at a regular interval and events are marked in the file in one of the columns with TaskA_0 representing the start of an event, and TaskA_1 representing the end. this is a snippet of the data:
Time Data 1 Data 2 Data 3 Data 4 Event Name
13:38:41.888 0.719460527 0.701654664 0.221332969 0.012234448 Task A_0
13:38:41.947 0.437707516 0.588673334 0.524042112 0.309975646 Task A_1
13:38:42.021 0.186847503 0.589175696 0.393891242 0.917737946 Task B_0
13:38:42.115 0.44490411 0.073132298 0.897701096 0.633815257 Task B_1
13:38:42.214 0.833793601 0.004524633 0.40950937 0.808966844 Task C_0
13:38:42.314 0.953997375 0.055717025 0.914080619 0.166492915 Task C_1
13:38:42.414 0.245698313 0.066643778 0.515709814 0.606289696 Task D_0
13:38:42.514 0.248038367 0.862138045 0.025489223 0.352926629 Task D_1
Currently I load this into matlab using xlsread , and then run a strfind to locate the row indices of the event markers in order to break my data up into tasks where each each task is the data in the adjacent columns between TaskA_0 and TaskA_1 (here there is no data between but normally there is, also between event names there are blank cells normally). Is this the best method for doing this? Once I have it in separate variables I then perform identical actions on each variable, usually basic statistics and some data plotting. If I want to batch process my data I have to rewrite these lines over and over to get the data broken up by task. Which even I know is wrong and horribly inefficient but I don't know how better to do this.
[Data,Text]= xlsread('C:\TestData.xlsx',2); %time column and event name column end up in text, as does the data headers, hence the +1 for the row indices
IndexTaskAStart = find(~cellfun(#isempty,strfind(Text(:,2),'TaskA_0')))+1;
IndexTaskAEnd = find(~cellfun(#isempty, strfind(Text(:,2),'TaskA_1')))+1;
TaskAData = Data([IndexTaskAStart:IndexTaskAEnd,:];
Now I can perform analysis on columns in TaskAData, and repeat the process for the remaining tasks.
Presuming you cannot change the format of the files, but do know which tasks you're searching for, you can still automate the search by creating a list of task names, just appending _0 and _1 onto the task names to search. Then do not create individual named variables but store in a cell array for easier looping:
tasknames = {'Task A', 'Task B', 'Task C'}
for n = 1:numel(tasknames)
first = find(~cellfun(#isempty,strfind(Text(:,2),[tasknames{n},'_0'])))+1;
last = find(~cellfun(#isempty, strfind(Text(:,2),[tasknames{n},'_1'])))+1;
task_data{n} = Data(first:last, :);
% whatever other analysis you require goes here
end
If there are a large number of tasknames but they follow some pattern, you might prefer to create them on the fly instead of preallocating a list in tasknames.
I'm trying to search across a large array of textual files in Mathematica 8 (12k+). So far, I've been able to plot the sheer numbers of times that a word appears (i.e. the word "love" appears 5,000 times across those 12k files). However, I'm running into difficulty determining the number of files in which "love" appears once - which might only be in 1,000 files, with it repeating several times in others.
I'm finding the documentation WRT FindList, streams, RecordSeparators, etc. a bit murky. Is there a way to set it up so it finds an incidence of a term once in a file and then moves onto the next?
Example of filelist:
{"89001.txt", "89002.txt", "89003.txt", "89004.txt", "89005.txt", "89006.txt", "89007.txt", "89008.txt", "89009.txt", "89010.txt", "89011.txt", "89012.txt", "89013.txt", "89014.txt", "89015.txt", "89016.txt", "89017.txt", "89018.txt", "89019.txt", "89020.txt", "89021.txt", "89022.txt", "89023.txt", "89024.txt"}
The following returns all of the lines with love across every file. Is there a way to return only the first incidence of love in each file before moving onto the next one?
FindList[filelist, "love"]
Thanks so much. This is my first post and I'm largely learning Mathematica through peer/supervisory help, online tutorials, and the documentation.
In addition to Daniel's answer, you also seem to be asking for a list of files where the word only occurs once. To do that, I'd continue to run FindList across all the files
res =FindList[filelist, "love"]
Then, reduce the results to single lines only, via
lines = Select[ res, Length[#]==1& ]
But, this doesn't eliminate the cases where there is more than one occurrence in a single line. To do that, you could use StringCount and only accept instances where it is 1, as follows
Select[ lines, StringCount[ #, RegularExpression[ "\\blove\\b" ] ] == 1& ]
The RegularExpression specifies that "love" must be a distinct word using the word boundary marker (\\b), so that words like "lovely" won't be included.
Edit: It appears that FindList when passed a list of files returns a flattened list, so you can't determine which item goes with which file. For instance, if you have 3 files, and they contain the word "love", 0, 1, and 2 times, respectively, you'd get a list that looked like
{, love, love, love }
which is clearly not useful. To overcome this, you'll have to process each file individually, and that is best done via Map (/#), as follows
res = FindList[#, "love"]& /# filelist
and the rest of the above code works as expected.
But, if you want to associate the results with a file name, you have to change it a little.
res = {#, FindList[#, "love"]}& /# filelist
lines = Select[res,
Length[ #[[2]] ] ==1 && (* <-- Note the use of [[2]] *)
StringCount[ #[[2]], RegularExpression[ "\\blove\\b" ] ] == 1&
]
which returns a list of the form
{ {filename, { "string with love in it" },
{filename, { "string with love in it" }, ...}
To extract the file names, you simply type lines[[All, 1]].
Note, in order to Select on the properties you wanted, I used Part ([[ ]]) to specify the second element in each datum, and the same goes for extracting the file names.
Help > Documentation Center > FindList item 4:
"FindList[files,text,n]
includes only the first n lines found."
So you could set n to 1.
Daniel Lichtblau