使用MATLAB进行DJing(低电平I/O)
好了,各位,这是一周中我学习如何用MATLAB做奇怪事情的时间。这周是DJing。我需要做的是找出如何使我的函数输出长度最接近剩余时间的歌曲的名称。例如,如果我在炫耀我的DJ技能,我还有3:22的时间,我必须选择一首长度最接近剩余时间的歌曲(可以更短或更长)。我有一个.txt文件可供选择使用MATLAB进行DJing(低电平I/O),matlab,loops,file-io,text-files,cell-array,Matlab,Loops,File Io,Text Files,Cell Array,好了,各位,这是一周中我学习如何用MATLAB做奇怪事情的时间。这周是DJing。我需要做的是找出如何使我的函数输出长度最接近剩余时间的歌曲的名称。例如,如果我在炫耀我的DJ技能,我还有3:22的时间,我必须选择一首长度最接近剩余时间的歌曲(可以更短或更长)。我有一个.txt文件可供选择 Test Case song1 = pickSong('Funeral.txt', '3:13') song1 => 'Neighborhood #2 (Laika)' The file for th
Test Case
song1 = pickSong('Funeral.txt', '3:13')
song1 => 'Neighborhood #2 (Laika)'
The file for this looks like:
1. Neighborhood #1 (Tunnels) - 4:48
2. Neighborhood #2 (Laika) - 3:33
3. Une annee sans lumiere - 3:40
4. Neighborhood #3 (Power Out) - 5:12
5. Neighborhood #4 (7 Kettles) - 4:49
6. Crown of Love - 4:42
7. Wake Up - 5:39
8. Haiti - 4:07
9. Rebellion (Lies) - 5:10
10. In the Backseat - 6:21
我已经计划好了,我的问题是填充我的细胞阵列。它只输入最后一首歌,然后在循环运行后将其更改为a-1。我试过三种不同的方法,最后一种是最复杂的(而且看起来很糟糕)。一旦我将单元格数组设置为正确的形式(作为完整的歌曲列表,而不仅仅是-1),我就应该清楚了
function[song] = pickSong(file_name,time_remain)
Song_list = fopen(file_name, 'r'); %// Opens the file
Song_names = fgetl(Song_list); %// Retrieves the lines, or song names here
Songs_in = ''; %// I had this as a cell array first, but tried to populate a string this time
while ischar(Songs) %// My while loop to pull out the song names
Songs_in = {Songs_in, Songs};
Songs = fgetl(Song_list);
if ischar(Songs_in) %//How I was trying to populate my string
song_info = [];
while ~isempty(Songs_in)
[name, time] = strtok(Songs_in);
song_info = [song_info {name}];
end
end
end
[songs, rest] = strtok(Songs, '-');
[minutes, seconds] = strtok(songs, ':');
[minutes2, seconds2] = strtok(time_remain, ':')
all_seconds = (minutes*60) + seconds; %// Converting the total time into seconds
all_seconds2 = (minutes2*60) + seconds2;
song_times = all_seconds;
time_remain = all_seconds2
time_remain = min(time_remain - song_times);
fclose(file_name);
end
请并感谢您的帮助:)
一个棘手的案例:
song3 = pickSong('Resistance.txt', '3:57')
song3 => 'Exogenesis: Symphony Part 2 (Cross-Pollination)'
1. Uprising - 5:02
2. Resistance - 5:46
3. Undisclosed Desires - 3:56
4. United States of Eurasia (+Collateral Damage) - 5:47
5. Guiding Light - 4:13
6. Unnatural Selection - 6:54
7. MK ULTRA - 4:06
8. I Belong to You (+Mon Coeur S'ouvre a Ta Voix) - 5:38
9. Exogenesis: Symphony Part 1 (Overture) - 4:18
10. Exogenesis: Symphony Part 2 (Cross-Pollination) - 3:57
11. Exogenesis: Symphony Part 3 (Redemption) - 4:37
您可以使用
textscan
进行管理,如下所示:
function[song,len] = pickSong(file_name,time_remain)
fid = fopen(filename);
toks = textscan(fid,'%[^-] - %d:%d');
songs = toks{1};
song_len = double(toks{2}*60 + toks{3});
[min_rem, sec_rem] = strtok(time_remain, ':');
time_rem = str2double(min_rem)*60 + str2double(sec_rem(2:end));
[len,i] = min(abs(time_rem - song_len));
song = songs{i};
请注意,只有当您的歌曲名称中没有'-'字符时,这才有效
编辑:这里有一个对任何歌曲标题都有效的解决方案:
function[song,len] = pickSong(file_name,time_remain)
file = fileread(file_name);
toks = regexp(file,'\d+. (.*?) - (\d+):(\d+)\n','tokens');
songs = cell(1,length(toks));
song_lens = zeros(1,length(toks));
for i=1:length(toks)
songs{i} = toks{i}{1};
song_lens(i) = str2double(toks{i}{2})*60 + str2double(toks{i}{3});
end
[min_rem, sec_rem] = strtok(time_remain, ':');
time_rem = str2double(min_rem)*60 + str2double(sec_rem(2:end));
[len,i] = min(abs(time_rem - song_lens));
song = songs{i};
regexp
是一个在字符串上运行正则表达式的MATLAB函数(在本例中为歌曲名称文件)。字符串'\d+。(.*)-(\d+):(\d+)\n'
扫描每一行,提取每首歌曲的名称和长度\d+
匹配一个或多个数字,而*?
匹配任何数字。括号用于对输出进行分组。因此,我们有:
match n digits, followed by a (string), followed by (n-digits):(n-digits)
括号中的所有内容都作为单元格数组返回给
toks
变量。for循环只是从结果单元格数组中提取歌曲名称和长度。您可以使用textscan
进行管理,如下所示:
function[song,len] = pickSong(file_name,time_remain)
fid = fopen(filename);
toks = textscan(fid,'%[^-] - %d:%d');
songs = toks{1};
song_len = double(toks{2}*60 + toks{3});
[min_rem, sec_rem] = strtok(time_remain, ':');
time_rem = str2double(min_rem)*60 + str2double(sec_rem(2:end));
[len,i] = min(abs(time_rem - song_len));
song = songs{i};
请注意,只有当您的歌曲名称中没有'-'字符时,这才有效
编辑:这里有一个对任何歌曲标题都有效的解决方案:
function[song,len] = pickSong(file_name,time_remain)
file = fileread(file_name);
toks = regexp(file,'\d+. (.*?) - (\d+):(\d+)\n','tokens');
songs = cell(1,length(toks));
song_lens = zeros(1,length(toks));
for i=1:length(toks)
songs{i} = toks{i}{1};
song_lens(i) = str2double(toks{i}{2})*60 + str2double(toks{i}{3});
end
[min_rem, sec_rem] = strtok(time_remain, ':');
time_rem = str2double(min_rem)*60 + str2double(sec_rem(2:end));
[len,i] = min(abs(time_rem - song_lens));
song = songs{i};
regexp
是一个在字符串上运行正则表达式的MATLAB函数(在本例中为歌曲名称文件)。字符串'\d+。(.*)-(\d+):(\d+)\n'
扫描每一行,提取每首歌曲的名称和长度\d+
匹配一个或多个数字,而*?
匹配任何数字。括号用于对输出进行分组。因此,我们有:
match n digits, followed by a (string), followed by (n-digits):(n-digits)
括号中的所有内容都作为单元格数组返回给
toks
变量。for循环只是从结果单元格数组中提取歌曲名称和长度。我将使用您已经编写的大部分内容编写答案,而不是建议完全不同的内容。虽然regexp
也是一个功能强大的函数(我喜欢正则表达式),但我发现它对于您目前所学的内容来说太高级了,所以现在让我们放弃它
通过这种方式,您可以了解代码的错误,以及我是多么棒的调试器(只是开玩笑)。当你在文本文件中阅读时,你所拥有的几乎是有效的。您在创建存储所有字符串的单元格数组时做了一个很好的选择
我还将借用MrAzzaman的逻辑,通过strtok计算以秒为单位的时间(顺便说一句,非常棒的工作)
另外,我要稍微改变一下你的逻辑,这样我就可以理解我该怎么做了。以下是基本算法:
-1
,我们就没有更多的歌曲可读了,所以请打破循环:
分隔。下一个将只包含歌曲本身的名称。现在,我们检查从步骤#3创建的单元数组中的每个元素
(a) 为了填充第一个单元格数组,我使用查找出现-
字符的所有实例。一旦我找到了这些发生的位置,我就选择了-
发生的最后一个位置。我用它来索引我们的歌曲字符串,跳过2个字符来跳过-
字符和空格字符。我们提取从这一点到行尾的所有字符以提取我们的时间
(b) 为了填充第二个单元格数组,我再次使用strfind
,但随后我计算出空格出现的位置,并选择第一个空格出现的位置的索引。这对应于歌曲编号和歌曲曲目之间的间隙。使用(a)中的索引结果,我通过将第一个空格的索引中的一个字符跳过到最后一个-
字符之前的两个字符来提取歌曲标题,以成功获取歌曲。这是因为在-
字符之前的歌曲标题的最后一个单词之间可能会有一个空格,因此我们希望删除该空格strtok
,就像您使用的那样,并通过:
拆分字符串。MrAzzaman也使用了这个,我将借用他的逻辑来计算每次所需的总秒数>> pickSong('Funeral.txt', '3:13')
ans =
'Neighborhood #2 (Laika)'
>> pickSong('Resistance.txt', '3:57')
ans =
'Exogenesis: Symphony Part 2 (Cross-Pollination)'
>> t = readSongsFile('Funeral.txt');
>> t.Minutes = fix(t.Duration/60); % add minutes column
>> t.Seconds = rem(t.Duration,60); % add seconds column
>> sortrows(t, 'Duration', 'descend') % show table sorted by duration
ans =
ID Title Duration Minutes Seconds
__ _____________________________ ________ _______ _______
10 'In the Backseat' 381 6 21
7 'Wake Up' 339 5 39
4 'Neighborhood #3 (Power Out)' 312 5 12
9 'Rebellion (Lies)' 310 5 10
5 'Neighborhood #4 (7 Kettles)' 289 4 49
1 'Neighborhood #1 (Tunnels)' 288 4 48
6 'Crown of Love' 282 4 42
8 'Haiti' 247 4 7
3 'Une annee sans lumiere' 220 3 40
2 'Neighborhood #2 (Laika)' 213 3 33
% find songs that are at least 5 minutes long
>> t(t.Minutes >= 5,:)
% songs with the word "Neighborhood" in the title
>> t(~cellfun(@isempty, strfind(t.Title, 'Neighborhood')),:)