首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >基于MATLAB的DJing (低电平I/O)

基于MATLAB的DJing (低电平I/O)
EN

Stack Overflow用户
提问于 2014-10-09 16:36:36
回答 3查看 178关注 0票数 0

好吧,各位,这是一个星期的时间,我学习如何用MATLAB做奇怪的事情。这周是DJing。我需要做的是弄清楚如何让我的函数输出歌曲的名字,歌曲的长度最接近剩下的时间。例如,如果我展示我的DJing技能,而我还有3:22,我必须选择一首长度最接近剩下时间的歌曲(可以是短的,也可以是更长的)。我有一个.txt文件可供选择。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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),我就应该清楚了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

请并感谢您的帮助:)

麻烦的案件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-10-09 20:12:04

我将用你已经写的大部分内容来写一个答案,而不是建议一些完全不同的东西。虽然regexp也很强大(我也喜欢正则表达式),但我发现它对于您目前所了解的东西来说太高级了,所以现在让我们放弃它吧。

这样,您就可以了解代码的错误所在,以及我的调试器有多棒(开玩笑)。当你在文本文件中阅读时,你所拥有的几乎是有效的。在创建存储所有字符串的单元格数组方面,您做了一个很好的选择。

我还将借用MrAzzaman先生在通过strtok (可怕的工作)以秒为单位计算时间时的逻辑。

另外,我要稍微改变一下你们的逻辑,这样我才能理解我将如何去做。以下是基本算法:

  1. 打开文件,像在代码中那样读第一行(歌曲)
  2. 初始化包含文本文件中第一首歌曲的单元格数组。
  3. 直到我们到达文本文件的末尾,读取整行并将其添加到单元格数组中。您还注意到,一旦您点击了-1,我们就没有更多的歌曲可读了,所以退出循环。
  4. 现在我们已经把歌曲放在一个单元格数组中,其中包括曲目号、歌曲和每首歌曲的时间,我们将再创建两个单元格数组。第一个将只将歌曲的时间存储为字符串,分钟和秒都由:分隔。下一个只会包含歌曲本身的名字。现在,我们遍历从步骤3创建的单元格数组中的每个元素。(A)为了填充第一个单元格数组,我使用strfind查找all出现的-字符所在位置。一旦我找到了这些发生的位置,我就会选择最后一个位置,即-发生的位置。我用它来索引我们的歌曲字符串,跳过两个字符来跳过-字符和空格字符。我们从这一点开始提取所有的字符到行的末尾来提取我们的时间。 (b)要填充第二个单元格数组,我再次使用strfind,但随后确定空间发生的位置,并选择第一个空格发生的位置的索引。这与歌曲编号与歌曲音轨之间的差距相对应。使用(a)中索引的结果,我从第一个空格的索引中跳过一个字符到索引- 字符前的索引,以成功地获得歌曲。这是因为在-字符之前的歌曲标题的最后一个字之间可能会有一个空格,所以我们想要删除这个空格。
  5. 接下来,对于步骤4中计算的第一个单元格数组中的每一首歌曲时间,我使用strtok,就像您使用过的那样,并将字符串由:拆分。MrAzzaman也使用了它,我将借用他的逻辑来计算每一次所需的总秒数。
  6. 最后,我们找出了哪个时间最接近剩余的时间。注意,我们还需要像第5步那样将剩余时间转换为秒。正如MrAzzaman所说,您可以在MATLAB中使用min函数,并使用函数的第二输出。这将告诉数组中的发生了最小值。因此,我们只需搜索每首歌的剩馀时间和经过的时间之间的最小差异。请注意,您说过您不关心您是否过去或在过去的时间。您只需要最近的时间。在这种情况下,您需要获得时间差的绝对值。假设你有一首歌花了3:59,另一首歌是6:00,剩下的时间是4:00。假设你的曲目中没有4:00长的歌曲,你会想要选择3:59的歌曲。但是,如果您从较长的轨道(6:00)减去剩余的时间,您将得到一个负差,min将返回此轨道.不是3:59的那首歌。这就是你需要取绝对值的原因,所以这会忽略你是在剩余的时间内还是在剩余的时间内。
  7. 一旦我们知道了选择哪首歌,返回给我们最小的歌曲名称。确保你也关闭了文件!

下面是代码,不需要再多说了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function [song] = pickSong(file_name, time_remain)

% // Open up the file
fid = fopen(file_name, 'r');

%// Read the first line
song_name = fgetl(fid);

%// Initialize cell array
song_list = {song_name};

%// Read in the song list and place
%// each entry into a cell array
while ischar(song_name)
    song_name = fgetl(fid);
    if song_name == -1
        break;
    end
    song_list = [song_list {song_name}];
end

%// Now, for each entry in our song list, find all occurrences of the '-'
%// with strfind, and choose the last index that '-' occurs at
%// Make sure you skip over by 2 spaces to remove the '-' and the space
song_times = cell(1,length(song_list));
song_names = cell(1,length(song_list));
for idx = 1 : length(song_list)
    idxs = strfind(song_list{idx}, '-');
    song_times{idx} = song_list{idx}(idxs(end)+2:end);

    idxs2 = strfind(song_list{idx}, ' ');
    %// Figure out the index of where the first space is, then extract
    %// the string that starts from 1 over, to two places before the 
    %// last '-' character
    song_names{idx} = song_list{idx}(idxs2(1)+1 : idxs(end)-2);
end

%// Now we have a list of times for each song.  Tokenize by the ':' to 
%// separate the minutes and times, then calculate the number of seconds
%// Logic borrowed by MrAzzaman
song_seconds = zeros(1,length(song_list));
for idx = 1 : length(song_list)
    [minute_str, second_str] = strtok(song_times{idx}, ':');
    song_seconds(idx) = str2double(minute_str)*60 + str2double(second_str(2:end));
end

%// Now, calculate how much time is remaining from the input
[minute_str, second_str] = strtok(time_remain, ':');
seconds_remain = str2double(minute_str)*60 + str2double(second_str(2:end));

%// Now, choose the song that is closest to the amount of time
%// elapsed
[~,song_to_choose] = min(abs(seconds_remain - song_seconds));

%// Return the song you want
song = song_names{song_to_choose};

%// Close the file
fclose(fid);

end

在上面给出的两个例子中,这是我得到的输出。我冒昧地创建了自己的文本文件,其中包含了您的音乐(非常棒的品味):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>> song1 = pickSong('Funeral.txt', '3:13')

song1 =

Neighborhood #2 (Laika)

>> song2 = pickSong('Resistance.txt', '3:57')

song2 =

Exogenesis: Symphony Part 2 (Cross-Pollination)
票数 1
EN

Stack Overflow用户

发布于 2014-10-10 21:25:11

以下是我的实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function song = pickSong(filename, time_remain)
    % read songs file into a table
    t = readSongsFile(filename);

    % query song length (in seconds)
    len = str2double(regexp(time_remain, '(\d+):(\d+)', ...
        'tokens', 'once')) * [60;1];

    % find closest match
    [~,idx] = min(abs(t.Duration - len));

    % return song name
    song = t.Title(idx);
end

function t = readSongsFile(filename)
    % read the whole file (as a cell array of lines)
    fid = fopen(filename,'rt');
    C = textscan(fid, '%s', 'Delimiter',''); C = C{1};
    fclose(fid);

    % parse lines of the form: "0. some name - 00:00"
    C = regexp(C, '^(\d+)\.\s+(.*)\s+-\s+(\d+):(\d+)$', 'tokens', 'once');
    C = cat(1, C{:});

    % extract columns and create a table
    t = table(str2double(C(:,1)), ...
        strtrim(C(:,2)), ...
        str2double(C(:,3:4)) * [60;1], ...
        'VariableNames',{'ID','Title','Duration'});
    t.Properties.VariableUnits = {'', '', 'sec'};
end

我们应该从测试文件中得到预期的结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>> pickSong('Funeral.txt', '3:13')
ans = 
    'Neighborhood #2 (Laika)'

>> pickSong('Resistance.txt', '3:57')
ans = 
    'Exogenesis: Symphony Part 2 (Cross-Pollination)'

注意:上面的代码使用MATLAB表来存储数据,这样可以方便地操作。例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>> 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')),:)
票数 2
EN

Stack Overflow用户

发布于 2014-10-09 17:10:51

您可以使用textscan来管理这一点,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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};

请注意,只有当您的歌曲名称中没有“-”字符时,这才会有效。

编辑:这是一个解决方案,(应该)在任何歌曲标题上工作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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+匹配一个或多个数字,而.*?匹配任何数字。括号用于对输出进行分组。因此,我们有:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
match n digits, followed by a (string), followed by (n-digits):(n-digits)

括号中的所有内容都作为单元格数组返回给toks变量。for循环只是从结果单元格数组中提取歌曲名称和长度。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26290154

复制
相关文章
JS 函数中的 arguments 类数组对象
众所周知,js 是一门非常灵活的语言。当我们在 js 中调用一个函数时,经常会给函数传递一些参数,js 把调用函数时传入的全部实参存储到一个叫做 arguments 的类数组对象里面
很酷的站长
2022/12/04
5.5K0
JS 函数中的 arguments 类数组对象
js中的对象
面向对象编程(Object Oriented Programming,缩写为 OOP)是目前主流的编程范式。它将真实世界各种复杂的关系,抽象为一个个对象,然后由对象之间的分工与合作,完成对真实世界的模拟。
用户4940950
2019/03/26
7K0
JS中对象+构造函数+原型对象谈恋爱了嘛。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script> function Person(myName,myAge) { this.name=myName; this.age=myAge; this.currentType="构造函数中的属性"; this.say=function() { console.log("构造函数里面的方法");
贵哥的编程之路
2020/10/28
1.2K0
JS中对象+构造函数+原型对象谈恋爱了嘛。
JS-比较函数中嵌套函数,可以排序【对象数组】
1 function createCompareFun(propertyName){ 2 return function(object1,object2){ 3 var value1 = object1[propertyName]; 4 var value2 = object2[propertyName]; 5 if(value1>value2){
xing.org1^
2018/05/17
4.9K0
js中对象
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>03_对象</title> </head> <body> <!-- 1. 什么是
李才哥
2020/03/28
9K0
js中的函数
console.log(fn instanceof Object) // 是Object类型的实例
李才哥
2020/08/17
6.5K0
js中的函数
js中的函数
console.log(fn instanceof Object) // 是Object类型的实例
李才哥
2020/03/28
5.3K0
js中的函数
js---对象 和 函数this
   当函数被保存为一个对象的属性时,它就可称为这个对象的方法。当一个方法被调用时,this被绑定到这个对象上。如果调用表达式包含一个提取属性的动作(. 或 []),那么它被称为方法调用。例如:
小蔚
2019/09/11
1.3K0
直接写和放在函数中不同的R语言用法
df$A可以索引数据框df中列名为A的列的所有值。那么假如列名是一个R对象怎么做?
生信宝典
2022/01/19
1.9K0
JavaScript中的函数、对象
JS中的函数 声明方式 方式一 function 函数名(){ 函数体 } 方式二 var 函数名=function(){ 函数体 } 方式三 var 函数名=new
时间静止不是简史
2020/07/24
2.7K0
JavaScript中的函数、对象
Js中Symbol对象
ES6引入了一种新的基本数据类型Symbol,表示独一无二的值,最大的用法是用来定义对象的唯一属性名,Symbol()函数会返回symbol类型的值,该类型具有静态属性和静态方法,其静态属性会暴露几个内建的成员对象,它的静态方法会暴露全局的symbol注册,且类似于内建对象类,但作为构造函数来说它并不完整,因为它不支持语法new Symbol()。每个从Symbol()返回的symbol值都是唯一的,一个symbol值能作为对象属性的标识符。
WindRunnerMax
2020/10/26
5.1K0
Js中String对象
创建一个字符串可以通过字面量的方式,通过字面量创建的字符串变量在调用方法的时候能够自动转化为临时的包装对象,从而能够调用其构造函数的原型中的方法,也可以利用String对象生成字符串对象,此外在ES6标准还定义了模板字面量用以生成字符串的方式。
WindRunnerMax
2020/09/18
7.7K0
Js中Proxy对象
Proxy对象用于定义基本操作的自定义行为,例如属性查找、赋值、枚举、函数调用等。
WindRunnerMax
2020/11/24
2.6K0
JS中Arguments对象
arguments对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。此对象包含传递给函数的每个参数,第一个参数在索引0处。例如,如果一个函数传递了三个参数,你可以以如下方式引用他们:
Caleb
2020/11/03
2.2K0
Js中Reflect对象
Reflect是ES6起JavaScript内置的对象,提供拦截JavaScript操作的方法,这些方法与Proxy对象的handlers中的方法基本相同。
WindRunnerMax
2020/11/26
3.7K0
小程序的登录逻辑能否放在app.js中实现?
前言:做小程序开发的同学,可能都会考虑一个问题,用户登录这个方法是公用的,我们应该把这个方法放在哪里最合适呢? 看到上面的问题后,很大一部分刚入门同学都会直接把登录方法放在app.js里,并且有些同
连胜
2018/03/22
3.6K0
小程序的登录逻辑能否放在app.js中实现?
Js中Date对象
JavaScript的Date对象是用于处理日期和时间的全局对象,Date对象基于Unix Time Stamp,即自1970年1月1日UTC起经过的毫秒数。
WindRunnerMax
2020/10/26
21.4K0
Js中Math对象
Math是一个内置对象,它拥有一些数学常数属性和数学函数方法,Math用于Number类型,其不支持BigInt。
WindRunnerMax
2020/10/10
5.2K0
Js中Array对象
JavaScript的Array对象是用于构造数组的全局对象,数组是类似于列表的高阶对象。
WindRunnerMax
2020/10/26
9.9K0
Js中Number对象
JavaScript的Number对象是经过封装从而能够处理数字值的对象,Number对象由Number()构造器以及字面量声明的值在转化为包装对象时创建,JavaScript的Number类型为双精度IEEE 754 64位浮点类型。
WindRunnerMax
2020/10/10
3.4K0

相似问题

将对象放在键列表中。纯JS

211

如何将对象放在js中的HashMap中?

30

不应将JS函数声明放在块中。

11

自动释放在函数调用中创建的对象

34

将函数放在对象中的最好方法?

13
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文