Is there a way in R to write vector comprehension using the paste function?
I simply need to get a one string representation of a (long) vector (data), like this:
data = [1, 58, 120]
s = paste(data[1], data[2], data[3], sep=", ")
Isn't there a nicer solution than do this in a for-loop?
I found this about comprehensions in R:
List comprehension in R
but it does not seem to work with paste.
Like #dickoa already commented, reducing a vector s into one string separated by , you can use paste:
data <- c(1, 2, 3)
paste(data, collapse = ", ")
Related
Let's cut to the chase:
I want to write an iterative print statement, so that given
names = ["val_loss","accuracy","f2_loss"]
values= [0.2454431134, 0.832532234, 0.982762611]
the script should print so that numbers are round off to 6 decimal places, and the list is dynamically iterated on.
Example:
val_loss: 0.245443, accuracy: 0.832532, f2_loss: 0.982762
The kind of iterator I want is something like:
strr = [names[i],":",values[i] for i in range(len(metrics)]
but of course the above doesn't work because I'm not a python wiz. and cannot always write a non-trivial list iterator.
Thanks for your help.
You could use zip and fancy formatting ;)
strs = []
for (name, value) in zip(names, values):
strs.append("{}:{:.6f}".format(name, value))
print(', '.join(strs))
Or, as a fancy 1-liner...
print(', '.join(("{}:{:.6f}".format(n, v) for (n, v) in zip(names, values))))
Explanation
In Python2, use itertools.izip instead of zip, in Python3, use zip. Zip allows you to lazily merge N-iterables and create tuples of N-length, so zip([1, 2, 3], [4, 5, 6]) effectively becomes [(1, 4), (2, 5), (3, 6)]. zip is a great tool for any Python programmer.
As for the formatting piece, you should read the documentation. A quick explanation is f stands for floating pointer numbers, {} is a replacement group, and :.6f means a float with a max of 6 decimals.
you could do like this:-
strr = [name + ":" + str(value) + "," for name in names for value in values]
Given two lists (a and b), I'd like to replace three elements of list 'a' with three elements of list 'b'. Currently I am using an expression like this:
a[0], a[5], a[7] = b[11], b[99], b[2]
As I need to do such operations very frequently with lots of different arrays I am wondering if there is a more compact solution for this problem (the number of elements I need to replace is always 3 though). I was thinking about something like:
a[0,5,7] = b[11,99,2]
Which obviously does not work.
If you've a python list you can do something like this :
toReplace = [0,5,7]
targetIndices = [11, 99, 2]
for i,j in zip(toReplace, targetIndices): a[i] = b[j]
If you've a numpy array, it's even simpler :
a[toReplace] = b[targetIndices]
#i.e, a[[0,5,7]] = b[[11, 99, 2]]
There might be some better solutions but this does the trick:
ind1 = [0,5,7]
ind2 = [11,99,2]
for i in range(len(ind1)):
a[ind1[i]]=b[ind2[i]]
Say I have a list of strings, like so:
strings = ["abc", "def", "ghij"]
Note that the length of a string in the list can vary.
The way you generate a new string is to take one letter from each element of the list, in order. Examples: "adg" and "bfi", but not "dch" because the letters are not in the same order in which they appear in the list. So in this case where I know that there are only three elements in the list, I could fairly easily generate all possible combinations with a nested for loop structure, something like this:
for i in strings[0].length:
for ii in strings[1].length:
for iii in strings[2].length:
print(i+ii+iii)
The issue arises for me when I don't know how long the list of strings is going to be beforehand. If the list is n elements long, then my solution requires n for loops to succeed.
Can any one point me towards a relatively simple solution? I was thinking of a DFS based solution where I turn each letter into a node and creating a connection between all letters in adjacent strings, but this seems like too much effort.
In python, you would use itertools.product
eg.:
>>> for comb in itertools.product("abc", "def", "ghij"):
>>> print(''.join(comb))
adg
adh
adi
adj
aeg
aeh
...
Or, using an unpack:
>>> words = ["abc", "def", "ghij"]
>>> print('\n'.join(''.join(comb) for comb in itertools.product(*words)))
(same output)
The algorithm used by product is quite simple, as can be seen in its source code (Look particularly at function product_next). It basically enumerates all possible numbers in a mixed base system (where the multiplier for each digit position is the length of the corresponding word). A simple implementation which only works with strings and which does not implement the repeat keyword argument might be:
def product(words):
if words and all(len(w) for w in words):
indices = [0] * len(words)
while True:
# Change ''.join to tuple for a more accurate implementation
yield ''.join(w[indices[i]] for i, w in enumerate(words))
for i in range(len(indices), 0, -1):
if indices[i - 1] == len(words[i - 1]) - 1:
indices[i - 1] = 0
else:
indices[i - 1] += 1
break
else:
break
From your solution it seems that you need to have as many for loops as there are strings. For each character you generate in the final string, you need a for loop go through the list of possible characters. To do that you can make recursive solution. Every time you go one level deep in the recursion, you just run one for loop. You have as many level of recursion as there are strings.
Here is an example in python:
strings = ["abc", "def", "ghij"]
def rec(generated, k):
if k==len(strings):
print(generated)
return
for c in strings[k]:
rec(generated + c, k+1)
rec("", 0)
Here's how I would do it in Javascript (I assume that every string contains no duplicate characters):
function getPermutations(arr)
{
return getPermutationsHelper(arr, 0, "");
}
function getPermutationsHelper(arr, idx, prefix)
{
var foundInCurrent = [];
for(var i = 0; i < arr[idx].length; i++)
{
var str = prefix + arr[idx].charAt(i);
if(idx < arr.length - 1)
{
foundInCurrent = foundInCurrent.concat(getPermutationsHelper(arr, idx + 1, str));
}
else
{
foundInCurrent.push(str);
}
}
return foundInCurrent;
}
Basically, I'm using a recursive approach. My base case is when I have no more words left in my array, in which case I simply add prefix + c to my array for every c (character) in my last word.
Otherwise, I try each letter in the current word, and pass the prefix I've constructed on to the next word recursively.
For your example array, I got:
adg adh adi adj aeg aeh aei aej afg afh afi afj bdg bdh bdi
bdj beg beh bei bej bfg bfh bfi bfj cdg cdh cdi cdj ceg ceh
cei cej cfg cfh cfi cfj
I have another question that I'd like input on, of course no direct answers just something to point me in the right direction!
I have a string of numbers ex. 1234567890 and I want 1 & 0 to change places (0 and 9) and for '2345' & '6789' to change places. For a final result of '0678923451'.
First things I did was convert the string into a list with:
ex. original = '1234567890'
original = list(original)
original = ['0', '1', '2' etc....]
Now, I get you need to pull the first and last out, so I assigned
x = original[0]
and
y = original[9]
So: x, y = y, x (which gets me the result I'm looking for)
But how do I input that back into the original list?
Thanks!
The fact that you 'pulled' the data from the list in variables x and y doesn't help at all, since those variables have no connection anymore with the items from the list. But why don't you swap them directly:
original[0], original[9] = original[9], original[0]
You can use the slicing operator in a similar manner to swap the inner parts of the list.
But, there is no need to create a list from the original string. Instead, you can use the slicing operator to achieve the result you want. Note that you cannot swap the string elements as you did with lists, since in Python strings are immutable. However, you can do the following:
>>> a = "1234567890"
>>> a[9] + a[5:9] + a[1:5] + a[0]
'0678923451'
>>>
for i=1:N
f(i) = 'f'+i;
end
gives an error in MatLab. What's the correct syntax to initialize an array with N strings of the pattern fi?
It seems like even this is not working:
for i=1:4
f(i) = 'f';
end
You can concatenate strings using strcat. If you plan on concatenating numbers as strings, you must first use num2str to convert the numbers to strings.
Also, strings can't be stored in a vector or matrix, so f must be defined as a cell array, and must be indexed using { and } (instead of normal round brackets).
f = cell(N, 1);
for i=1:N
f{i} = strcat('f', num2str(i));
end
For versions prior to R2014a...
One easy non-loop approach would be to use genvarname to create a cell array of strings:
>> N = 5;
>> f = genvarname(repmat({'f'}, 1, N), 'f')
f =
'f1' 'f2' 'f3' 'f4' 'f5'
For newer versions...
The function genvarname has been deprecated, so matlab.lang.makeUniqueStrings can be used instead in the following way to get the same output:
>> N = 5;
>> f = strrep(matlab.lang.makeUniqueStrings(repmat({'f'}, 1, N), 'f'), '_', '')
f =
1×5 cell array
'f1' 'f2' 'f3' 'f4' 'f5'
Let me add another solution:
>> N = 5;
>> f = cellstr(num2str((1:N)', 'f%d'))
f =
'f1'
'f2'
'f3'
'f4'
'f5'
If N is more than two digits long (>= 10), you will start getting extra spaces. Add a call to strtrim(f) to get rid of them.
As a bonus, there is an undocumented built-in function sprintfc which nicely returns a cell arrays of strings:
>> N = 10;
>> f = sprintfc('f%d', 1:N)
f =
'f1' 'f2' 'f3' 'f4' 'f5' 'f6' 'f7' 'f8' 'f9' 'f10'
Using sprintf was already proposed by ldueck in a comment, but I think this is worth being an answer:
f(i) = sprintf('f%d', i);
This is in my opinion the most readable solution and also gives some nice flexibility (i.e. when you want to round a float value, use something like %.2f).
according to this it looks like you have to set "N" before trying to use it and it looks like it needs to be an int not string? Don't know much bout MatLab but just what i gathered from that site..hope it helps :)
Try the following:
for i = 1:4
result = strcat('f',int2str(i));
end
If you use this for naming several files that your code generates, you are able to concatenate more parts to the name. For example, with the extension at the end and address at the beginning:
filename = strcat('c:\...\name',int2str(i),'.png');