Hey i'm trying to transform a text file into an array,
tutorial:gf
bopeebo:dad
fresh:dad
dadbattle:dad
spookeez:spooky
Result:
songs=['tutorial','bopeebo','fresh','dadbattle','spokeez']
characters=['gf','dad','dad','dad','spooky']
The simplest way to do this would be to use io.lines(filename) to loop over the lines, using string.match to extract each k-v pair:
local songs, characters = {}, {}
for line in io.lines(filename) do
-- Uses .* to allow empty keys and values; use .+ instead to disallow
local song, character = line:match"(.*):(.*)"
table.insert(songs, song)
table.insert(characters, character)
end
I would however question whether two lists are the right data structure for the job. You'll probably want to leverage the hash part of the table instead:
local character_by_song = {}
for line in io.lines(filename) do
local song, character = line:match"(.*):(.*)"
character_by_song[song] = character
end
This would allow you to look up which character is assigned to a specific song very efficiently (in constant time).
Related
my #buildno = $mech->xpath('/html/body/form/table/tbody/tr[2]/td[3]/table
/tbody/tr[2]/td/table/tbody/tr[1]/td/table/tbody/tr[1]/td', type =>
$mech->xpathResult('STRING_TYPE'));
I have the above code which contains a string. I need to capture the word beginning with CSR contained in the array within a string. There is only one element #buildno[0]. I need to keep the word and remove everything else in the string. I have tried using the m// way however it only returns a boolean telling me that the word exists. I have also tried subtituting s/// however I can only remove the word that I need to keep, I cannot figure out a way to reverse that function.
EDIT
I have managed to split the string up and put it into a new array so each word is a seperate index.
my $buildno = join('', #buildno);
my #build = split(' ',$buildno);
print #build[1];
The word I am looking for in this instance is the second element in the array as it is the second word #build[1]however the word may not always be the second word in the string, it could be the fourth word for example. My purpose is to capture that specific word for later use.
You may match the desired word using m// storing it in a capture group and then replace the whole original string with that matched group:
do {$_ = $1 if /(?:^|\s)(CSR\S*)/} foreach #buildno;
Demo: https://ideone.com/1l7YJb
I have a similar issue as this post:
How to use variable inside %w{}
but my issue is a bit different. I want to take a string variable and convert it to an array using %w or %W.
text = gets.chomp # get user text string
#e.g I enter "first in first out"
words = %w[#{text}] # convert text into array of strings
puts words.length
puts words
Console output
1
first in first out
Keeps the text as a block of string and doesn't split it into an array words ["first","in", "first", "out"]
words = text.split (" ") # This works fine
words = %w[#{gets.chomp}] # This doesn't work either
words = %w['#{gets.chomp}'] # This doesn't work either
words = %W["#{gets.chomp}"] # This doesn't work either
words = %w("#{gets.chomp}") # This doesn't work either
%w is not intended to do any splitting, it's a way of expressing that the following string in the source should be split. In essence it's just a short-hand notation.
In the case of %W the #{...} chunks are treated as a single token, any spaces contained within are considered an integral part.
The correct thing to do is this:
words = text.trim.split(/\s+/)
Doing things like %W[#{...}] is just as pointless as "#{...}". If you need something cast as a string, call .to_s. If you need something split call split.
I have data stored in text files.The data is in 'cell array of string' after read it using textscan and contains various of colour name. Below is the content of my data:
name of colour
'lavender'
'lavenderblush'
'lemonchiffon'
'lightblue'
'lightcoral'
'lightcyan'
I want to create new array to group all color characters into the main color only (red, blue, orange, brown,etc).
I am really struggling to solve this problem. Thank you in advance for any help.
load_data = fopen('result.txt', 'r');
C = textscan(load_data, ' %s ');
fclose(load_data);
name = C{1,1};
group = char(name)
if group{:,1} == lavender
fprintf('purple');
else
fprintf('nothing');
end
This is my code but if I run this, always get error
Cell contents reference from a non-cell array object.
From your comment above, I assume you're having trouble with your code, not actually with the sorting of colors, or how to categorize them.
group is not a Cell array, it's a Char array. So in order to access its values you should use group(:,1) instead of group{:,1}
Remember that the number of columns in group is the number of characters in that line, normalized to the number of characters of the largest string in that set. So 2 issues here:
You can't use group(:,1), as it will get the first character of all the strings in that array. You should get the entire line for that string group(1,:). NB: I say string for simplicity, it's actually a char array.
'lavender' has only 10 characters, but it will have 15, as per the largest string. So the string comparison doesn't quite work, unless you add the extra blank spaces to compensate
You can try out the code below:
load_data = fopen('result.txt', 'r');
C = textscan(load_data, ' %s ');
fclose(load_data);
name = C{1,1};
if name{1,:} == '''lavender'''
fprintf('purple');
else
fprintf('nothing');
end
I assume that your TXT file actually has the string 'lavender', in this case I used character escape '''lavender'''.
The error you are getting is fairly clear. Once you have called char(name), you are working with a regular character array (i.e. a string) and no longer a cell array. Braces (i.e. {}) are used to index cell arrays so you should instead be using parentheses (i.e. ()). Note this actually happens as soon as you index using {} so C{1,1} would actually return a string already and the char line is thus redundant:
if group(:,1) == lavender
I suspect you actually want something more like
name = C{1};
group = char(name) %this line is redundant because C{1} already extracts a string
if strcmp(group,lavender)
fprintf('purple');
else
fprintf('nothing');
end
but it's impossible to say since you did not define the variable lavender.
I would also question what data structure you intend to use. I'm going to assume you actually have some way of categorizing the colours? I'm going to assume this is manual in which case I would suggest converting your txt file to a csv file and putting your manual colour categories as a second column but I'll leave the implementation details to you.
Lets say you have 3 colour categories for now, 'purple', 'blue', and 'orange', my suggestion is to use a logical matrix that has 3 columns (1 per colour category) and n rows where n is the number of rows in your text file (i.e. the number of colours you need to categorize).
Now I'm going to assume you have some sort of mapping function that can categorize your colours so map('lavender') returns 'purple' and map('lightcyan') returns 'blue'
First we should make a cell array of categories that we can use to map the category string to its column number:
categories = {'purple'
'blue'
'orange'}
and the result will go in the logical matrix categorized
load_data = fopen('result.txt', 'r');
C = textscan(load_data, ' %s ');
fclose(load_data);
n = numel(C);
categories = {'purple'
'blue'
'orange'};
categorized = false(n, numel(categories)); %preallocation
for row = 1:n
colour = C{row};
category = map(colour); %you need to implement this map function yourself.
categorized(row, strcmp(category, categories)) = true;
end
I am trying to create a string array which will be fed with string values read from a text file this way:
labels = textread(file_name, '%s');
Basically, for each string in each line of the text file file_name I want to put this string in 10 positions of a final string array, which will be later saved in another text file.
What I do in my code is, for each string in file_name I put this string in 10 positions of a temporary cell array and then concatenate this array with a final array this way:
final_vector='';
for i=1:size(labels)
temp_vector=cell(1,10);
temp_vector{1:10}=labels{i};
final_vector=horzcat(final_vector,temp_vector);
end
But when I run the code the following error appears:
The right hand side of this assignment has too few values to satisfy the left hand side.
Error in my_example_code (line 16)
temp_vector{1:10}=labels{i};
I am too rookie in cell strings in matlab and I don't really know what is happening. Do you know what is happening or even have a better solution to my problem?
Use deal and put the left hand side in square brackets:
labels{1} = 'Hello World!'
temp_vector = cell(10,1)
[temp_vector{1:10}] = deal(labels{1});
This works because deal can distribute one value to multiple outputs [a,b,c,...]. temp_vector{1:10} alone creates a comma-separated list and putting them into [] creates the output array [temp_vector{1}, temp_vector{2}, ...] which can then be populated by deal.
It is happening because you want to distribute one value to 10 cells - but Matlab is expecting that you like to assign 10 values to 10 cells. So an alternative approach, maybe more logic, but slower, would be:
n = 10;
temp_vector(1:n) = repmat(labels(1),n,1);
I also found another solution
final_vector='';
for i=1:size(labels)
temp_vector=cell(1,10);
temp_vector(:,1:10)=cellstr(labels{i});
final_vector=horzcat(final_vector,temp_vector);
end
I need to transfer a text from a text file/string to a Table with a 2 positions vector. Like this:
Text File:
Gustavo 20
Danilo 20
Dimas 40
Table
Names = {{Gustavo,20},{Danilo,20},{Dimas,40}}
Need help to do this.
You can use io.lines() for this.
vectorarray = {}
for line in io.lines(filename) do
local w, n = string.match(line, "^(%w+)"), string.match(line, "(%d+)$")
table.insert(vectorarray, {w, n})
end
This is, of course, assuming that it's an absolute end of line and absolute start, and there is only those two options per line. If you're using the file name in many other places, then you could set a global variable for the file name and call it each time, such as:
arrayfile = "C:/arrayfile.txt"
Either way, make sure you put the correct path in quotation marks in the file name.
A shorter variation of Josh's answer that directly puts the result into the table. This matches alphabetic names followed by at least one space and numbers but you can change the pattern as needed:
Names = {}
for line in io.lines(filename) do
Names[ #Names+1 ] = {line:match('(%a+)%s+(%d+)')}
end