質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Q&A

解決済

7回答

3429閲覧

JavaScript: 文字列から多次元配列を生成するには?

t-cool

総合スコア71

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

0グッド

1クリップ

投稿2020/06/21 21:51

編集2020/06/22 05:46

JavaScript の質問です。

次の文字列のデータ captions があるとします。

時刻と文字が繰り返し現れるデータです。

let cartions = "3 - My nail, 6 is very big. 11 (lively music) 26 - Konnichiwa everyone? 27 - Konnichiwa. 29 - Oh Japan. 32 - I wanna scream. 33 May I? 35 (screams) 43 - Oh that's Japanese. 45 I know it. 49 - Oh. 50 - Oh it smells good. 53 (mumbles) 56 - Yum. 58 (mumbles) 65 - Spicy. 70 - I wonder why they make it"

この captions を、JavaScript で以下の多次元配列に変換しるには、どうすればいいでしょうか?

[["3", "- My nail,"], ["6", "is very big."], ["11", "(lively music)"], ["26", "- Konnichiwa everyone?"], ["27","Oh Japan."], ["29","- I wanna scream."], ["32","May I?"], ["35","(screams)"], ["43","- Oh that's Japanese."], ["45","I know it."], ["49","- Spicy."], ["56","- Yum."], ["58","(mumbles)"], ["65","- Spicy."], ["70","- I wonder why they make it"], ]

ご助言、よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hentaiman

2020/06/21 22:30

うまくいかないのは処理のどの部分ですか?
yambejp

2020/06/22 00:39

一行目の配列がとじてません
miyabi_takatsuk

2020/06/22 03:02

もうすでに正答がいくつも出ておりますが、 まずは、自身でどこまで調べて、やって、ここがうまく行かなかった、などを記載し、 丸投げにならないようにならないようにしましょう。
guest

回答7

0

ベストアンサー

こんにちは。一例を挙げます。

javascript

1captions.split(/(?=\b\d)/).map(str => /^(\d+)\s+(.+[^\s]+)/.exec(str).slice(1));

補足

上記のコードによって、ご質問にある captions は、意図通りの二次元配列に分割されます。ただし検討事項として、ご質問にある

時刻と文字が繰り返し現れるデータ

の「文字」の部分に属すと思われる数字があっても、それも「時刻」とみて区切ってしまいます。たとえば、ご質問にある captions には

11 (lively music)

が含まれていますが、これが以下

11 (lively 10 musics)

だったりすると、分割によって

javascript

1[ '11', '(lively 10 musics)' ]

になって欲しいものと思いますが、上記のコードだと、以下のような時刻と文字の組が二つあるものとして分割されます。

javascript

1[ '11', '(lively' ], [ '10', 'musics)' ]

投稿2020/06/22 02:45

jun68ykt

総合スコア9058

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

t-cool

2020/06/22 06:27

ご助言、ありがとうございました!
jun68ykt

2020/06/22 07:53

どういたしまして???? 参考になれば幸いです。
guest

0

String.prototype.splitの引数に正規表現オブジェクトを渡せばうまくいきそうです。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/split
の「RegExp で分割して結果に区切り文字列の一部を含める」のセクションをどうぞ。

JavaScript

1const content = "1 あ 22 い 333 う"; 2 3const words = content.split(/([0-9]+)/).slice(1); 4for (let i = 0; i < words.length; i += 2) { 5 console.log([words[i], words[i + 1]]); 6} 7 8/* 9[ '1', ' あ ' ] 10[ '22', ' い ' ] 11[ '333', ' う' ] 12*/

投稿2020/06/21 22:52

draq

総合スコア2577

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

t-cool

2020/06/22 06:28

ご助言、ありがとうございました!
guest

0

どこまでの処理が必要かわりませんがこんな感じ

投稿2020/06/22 00:43

編集2020/06/22 00:55
yambejp

総合スコア116724

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2020/06/22 00:54 編集

let cartions = "3 - My nail, 6 is very big. 11 (lively music) 26 - Konnichiwa everyone? 27 - Konnichiwa. 29 - Oh Japan. 32 - I wanna scream. 33 May I? 35 (screams) 43 - Oh that's Japanese. 45 I know it. 49 - Oh. 50 - Oh it smells good. 53 (mumbles) 56 - Yum. 58 (mumbles) 65 - Spicy. 70 - I wonder why they make it" const num=2; var tmp=cartions.replace(/(\d+)/g,"\n$1\n").split(/\n/); tmp=tmp.splice(1,tmp.length-2); tmp=tmp.map(x=>x.replace(/^\s+|\s+$/g,"")); const result=tmp.reduce((x,y)=>x[x.length-1].length===num?(x.push([y]),x):(x[x.length-1].push(y),x),[[]]); console.log(result);
yambejp

2020/06/22 00:56

課題:先頭が数値じゃない場合、末尾が数値の場合、どうするのでしょうか?
t-cool

2020/06/22 06:27

自前のデータだと先頭は数字なので、ご助言の方法で解決できました! ありがとうございました!
guest

0

RegExp.prototype.exec

JavaScriptの正規表現系機能は、gフラグを付与すると、() によるキャプチャが無効となる為、複数回のマッチで対応します。

  • RegExp#exec + 繰り返し構文
  • String#replace + コールバック関数

今回、String#replaceの返り値を必要としない為、前者で実装します。

JavaScript

1let string = "3 - My nail, 6 is very big. 11 (lively music) 26 - Konnichiwa everyone? 27 - Konnichiwa. 29 - Oh Japan. 32 - I wanna scream. 33 May I? 35 (screams) 43 - Oh that's Japanese. 45 I know it. 49 - Oh. 50 - Oh it smells good. 53 (mumbles) 56 - Yum. 58 (mumbles) 65 - Spicy. 70 - I wonder why they make it"; 2 3const reg = /\s*(\d+) - ((?:(?!\d+ - )[\s\S])+)|([\s\S])/g, array = []; 4let result; 5 6while (result = reg.exec(string)) { 7 if (result[3]) throw new Error('parse error'); 8 array.push([result[1], result[2]]); 9}

gフラグ付のRegExp#execは同じ場所に複数回マッチする事はありませんが、読み飛ばしは発生するので、([\s\S]) で意図せぬ読み飛ばしにパースエラーを返すように正規表現を組みます。

※未検証コードの為、期待通りに動作しない可能性があります。
アルゴリズムは使えると思います。

Re: t-cool さん

投稿2020/06/22 03:54

編集2020/06/22 03:57
think49

総合スコア18189

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

t-cool

2020/06/22 06:26

ご助言、ありがとうございました!
guest

0

時刻と文字が繰り返し現れるデータ

ご質問の修正を経てcaptionsは「秒単位の数値と文字が繰り返し現れるデータ」になっていますが、
初回の例では、正規表現で時刻フォーマット(hh:mm:dd)にマッチさせる方法が使えます。

javascript

1 2const firstData = "00:00:03 - My nail, 00:00:06 is very big. 00:00:11 (lively music) 00:00:26 - Konnichiwa everyone? 00:00:27 - Konnichiwa. 00:00:29 - Oh Japan. 00:00:32 - I wanna scream. 00:00:33 May I? 00:00:35 (screams) 00:00:43 - Oh that's Japanese. 00:00:45 I know it. 00:00:49 - Oh. 00:00:50 - Oh it smells good. 00:00:53 (mumbles) 00:00:56 - Yum. 00:00:58 (mumbles) 00:01:05 - Spicy. 00:01:10 - I wonder why they make it"; 3 4const parseCaptions = src => { 5 const int = n=>parseInt(n); 6 let rslt = [], segment, pointer = 0; 7 8 src.replace(/(\d{2}):(\d{2}):(\d{2})\s/g, (timeformat, hour, min, sec, offset)=>{ 9 10 if( !pointer ) segment=[]; 11 else { 12 segment.push( src.substring( pointer, offset ) ); 13 rslt.push( segment ); 14 segment = []; 15 pointer = offset; 16 } 17 segment.push( int(hour)*60*24 + int(min)*60 + int(sec) + "" ); 18 pointer += timeformat.length; 19 }); 20 21 segment.push( src.substring( pointer ) ); 22 rslt.push( segment ); 23 24 return rslt; 25} 26 27console.log( JSON.stringify(parseCaptions(firstData),null,2) );

ご助言、よろしくお願い致します

String#replace() の第二引数に関数を指定し、マッチしたタイミングの文字位置(offset)を活用すると、whileループで行うような字句解析が実現できます。


要件「時刻と文字が繰り返し現れるデータ」の文字に、数字の混入を許容する場合は「特定のフォーマット(という特徴)+任意の文字」の組み合わせのほうが、字句解析としては処理しやすい事例かもしれません。
処理対象のデータが改行された複数行テキストであるなど、他にも特徴があれば、より変換しやすくなると思います。

投稿2020/06/22 03:30

編集2020/06/22 03:40
AkitoshiManabe

総合スコア5434

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

t-cool

2020/06/22 06:26

ご助言、ありがとうございました!
guest

0

draqさんの回答はすごいですね。
正規表現でsplitできるんだ。勉強になりました。

単純なものならよいのですが
正規表現は複雑になると、可読性が悪く、可変性が低く、デバッグもしくにいので
あまり使うべきではないと思っている派なので普通のコードで実現してみました。

js

1let cartions = "3 - My nail, 6 is very big. 11 (lively music) 26 - Konnichiwa everyone? 27 - Konnichiwa. 29 - Oh Japan. 32 - I wanna scream. 33 May I? 35 (screams) 43 - Oh that's Japanese. 45 I know it. 49 - Oh. 50 - Oh it smells good. 53 (mumbles) 56 - Yum. 58 (mumbles) 65 - Spicy. 70 - I wonder why they make it" 2 3const result = []; 4let buffer = ''; 5const cartionsArray = cartions.split(' '); 6cartionsArray.forEach(value => { 7 if (buffer !== '' && _.isInteger(Number(value))) { 8 const bufferArray = buffer.split(' '); 9 result.push([bufferArray[0], bufferArray.slice(1, bufferArray.length - 1).join(' ')]); 10 buffer = ''; 11 } 12 buffer += value + ' '; 13}); 14 const bufferArray = buffer.split(' '); 15 result.push([bufferArray[0], bufferArray.slice(1, bufferArray.length - 1).join(' ')]); 16 17console.log(result);

実行結果は次の通りです。

0: (2) ["3", "- My nail,"] 1: (2) ["6", "is very big."] 2: (2) ["11", "(lively music)"] 3: (2) ["26", "- Konnichiwa everyone?"] 4: (2) ["27", "- Konnichiwa."] 5: (2) ["29", "- Oh Japan."] 6: (2) ["32", "- I wanna scream."] 7: (2) ["33", "May I?"] 8: (2) ["35", "(screams)"] 9: (2) ["43", "- Oh that's Japanese."] 10: (2) ["45", "I know it."] 11: (2) ["49", "- Oh."] 12: (2) ["50", "- Oh it smells good."] 13: (2) ["53", "(mumbles)"] 14: (2) ["56", "- Yum."] 15: (2) ["58", "(mumbles)"] 16: (2) ["65", "- Spicy."] 17: (2) ["70", "- I wonder why they make it"] length: 18

投稿2020/06/28 05:47

編集2020/06/28 06:17
standard-soft

総合スコア197

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

まずは、自分でコードを考えてくださいね

ヒントとしては文字列の規則性を考えてください。

それが解ったらその規則性をどのようにプログラムに当てはめていくか?

例えばindexOfなどを使ってみるとか
https://www.sejuku.net/blog/21049

indexOfを使ったアプローチが正解か?は解りませんがマズは色々試すことが重要です。

投稿2020/06/21 23:01

AMK

総合スコア765

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問