こんにちは
多重ではどうすればよいか分かりませんでした。
とのことですが、
多重
とは、具体的にはどのような階層構造の中に目的の配列があるのかについて、ご質問からは読み取れませんでしたので、全体の配列の中のどこにあっても、長さが2で要素が文字列か数字であるような
一番小さい配列
を拾い出すコードを回答します。なお、以下では、この
一番小さい配列
のことを minimal な配列
と呼び、 minimal な配列の先頭要素を head
, 2番目の要素を tail
と呼ぶことにして、これらを変数名やプロパティ名、関数名に使っています。
index.html
html
1 <! DOCTYPE html >
2 < html lang = " ja " >
3 < head >
4 < meta charset = " UTF-8 " >
5 < title > Q203923 </ title >
6 < script src = " https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js " > </ script >
7 < script src = " ./assort.js " > </ script >
8 < script >
9 function main ( ) {
10 var obj1 = document . getElementById ( "selfile" ) ;
11
12 obj1 . addEventListener ( "change" , function ( evt ) {
13
14 var file = evt . target . files ;
15 var reader = new FileReader ( ) ;
16 reader . readAsText ( file [ 0 ] ) ;
17
18 reader . onload = function ( ev ) {
19 var text = reader . result . toLowerCase ( ) ;
20 document . test . txt . value = text ;
21
22 var result = assort ( text ) ;
23
24 console . log ( result ) ;
25 }
26 } ) ;
27 }
28
29 document . addEventListener ( 'DOMContentLoaded' , main ) ;
30 </ script >
31 </ head >
32 < body >
33 < form name = " test " >
34 < input type = " file " id = " selfile " > < br >
35 < textarea name = " txt " rows = " 10 " cols = " 60 " readonly > </ textarea >
36 </ form >
37 </ body >
38 </ html >
上記で、選ばれたファイルの内容を受け取って、結果を返す assort
という関数を作りました。関数 assort
は、以下のファイル assort.js
の最後にあります。minimal な配列を収集した後、重複を除くための処理に、 lodash の uniqBy を使っています。
assort.js
javascript
1 const isMinimal = a => (
2 Array . isArray ( a ) &&
3 a . length === 2 &&
4 [ typeof a [ 0 ] , typeof a [ 1 ] ] . every (
5 t => [ 'number' , 'string' ] . includes ( t )
6 )
7 ) ;
8
9 const getMinimals = ( a , result = [ ] ) => {
10 if ( isMinimal ( a ) )
11 result . push ( a ) ;
12 else if ( Array . isArray ( a ) )
13 a . forEach ( e => { getMinimals ( e , result ) ; } )
14
15 return result ;
16 }
17
18 const compare = ( e1 , e2 ) => {
19 const type1 = typeof e1 ;
20 const type2 = typeof e2 ;
21
22 if ( type1 !== type2 ) {
23 return type1 === 'number' ? - 1 : 1
24 } else {
25 return type1 === 'number' ? e1 - e2 : e1 . localeCompare ( e2 )
26 }
27 } ;
28
29 const getKeys = ary =>
30 [ 'heads' , 'tails' ] . reduce ( ( m , k , i ) =>
31 m . set ( k , _ . uniq ( ary . map ( e => e [ i ] ) ) . sort ( compare ) )
32 , new Map ( ) ) ;
33
34 const assortByKeys = ( keys , ary ) => {
35 const heads = keys . get ( 'heads' ) . map ( k => ( {
36 value : k ,
37 minimalArrays : ary . filter ( e => e [ 0 ] === k )
38 } ) ) ;
39
40 const tails = keys . get ( 'tails' ) . map ( k => ( {
41 value : k ,
42 minimalArrays : ary . filter ( e => e [ 1 ] === k )
43 } ) ) ;
44
45 return { heads , tails }
46 }
47
48 const assort = text => {
49
50 // 先頭の '変数名=' を除去
51 text = text . replace ( / ^(.+)= / , '' )
52
53 // 配列要素として出現する変数名をダブルコーテーションで囲む。
54 const jsonStr = text . replace ( / ([a-z][a-z0-9]*) / g , name => ` " ${ name } " ` ) ;
55
56 // JSON文字列としてパース
57 const data = JSON . parse ( jsonStr ) ;
58
59 // 最小配列(要素の数が2個で、要素が数または文字列の配列) を収集
60 const minimals = _ . uniqBy ( getMinimals ( data ) , e => e . join ( ',' ) )
61
62 // 分類キーを作成
63 const keys = getKeys ( minimals )
64
65 // 最小配列を分類する
66 const result = assortByKeys ( keys , minimals )
67
68 return result ;
69 }
70
上記によって、以下のテキストファイル
input.txt
text
1 result4=[
2 [ [d,1], [b,2], [c,x], [d,y] ],
3 [ [a,y], [b,x], [c,2], [d,1] ]
4 ]
を読むと、result
には以下のようなオブジェクトが入ります。
javascript
1 {
2 heads : [
3 { value : "a" , minimalArrays : [ [ "a" , "y" ] ] } ,
4 { value : "b" , minimalArrays : [ [ "b" , 2 ] , [ "b" , "x" ] ] } ,
5 { value : "c" , minimalArrays : [ [ "c" , "x" ] , [ "c" , 2 ] ] } ,
6 { value : "d" , minimalArrays : [ [ "d" , 1 ] , [ "d" , "y" ] ] }
7 ] ,
8 tails : [
9 { value : 1 , minimalArrays : [ [ "d" , 1 ] ] } ,
10 { value : 2 , minimalArrays : [ [ "b" , 2 ] , [ "c" , 2 ] ] } ,
11 { value : "x" , minimalArrays : [ [ "c" , "x" ] , [ "b" , "x" ] ] } ,
12 { value : "y" , minimalArrays : [ [ "d" , "y" ] , [ "a" , "y" ] ] }
13 ]
14 }
また、以下のような入力
input2.txt
text
1 result5=[
2
3 [
4 [a,1],[b,5],[ [d,8], [c,3], [a,7], [c,5] ]
5 ],
6
7 [
8 [[ [d,8], [a,1] ], [c, 6], [[[ [x,y], [x,z], [x,5] ]]] ],
9 [f,6], [ [d, 7], [c, 5] ]
10 ]
11
12 ]
に対しても、以下が得られます。
javascript
1 {
2 heads : [
3 { value : "a" , minimalArrays : [ [ "a" , 1 ] , [ "a" , 7 ] ] } ,
4 { value : "b" , minimalArrays : [ [ "b" , 5 ] ] } ,
5 { value : "c" , minimalArrays : [ [ "c" , 3 ] , [ "c" , 5 ] , [ "c" , 6 ] ] } ,
6 { value : "d" , minimalArrays : [ [ "d" , 8 ] , [ "d" , 7 ] ] } ,
7 { value : "f" , minimalArrays : [ [ "f" , 6 ] ] } ,
8 { value : "x" , minimalArrays : [ [ "x" , "y" ] , [ "x" , "z" ] , [ "x" , 5 ] ] }
9 ] ,
10 tails : [
11 { value : 1 , minimalArrays : [ [ "a" , 1 ] ] } ,
12 { value : 3 , minimalArrays : [ [ "c" , 3 ] ] } ,
13 { value : 5 , minimalArrays : [ [ "b" , 5 ] , [ "c" , 5 ] , [ "x" , 5 ] ] } ,
14 { value : 6 , minimalArrays : [ [ "c" , 6 ] , [ "f" , 6 ] ] } ,
15 { value : 7 , minimalArrays : [ [ "a" , 7 ] , [ "d" , 7 ] ] } ,
16 { value : 8 , minimalArrays : [ [ "d" , 8 ] ] } ,
17 { value : "y" , minimalArrays : [ [ "x" , "y" ] ] } ,
18 { value : "z" , minimalArrays : [ [ "x" , "z" ] ] }
19 ]
20 }
上記の回答に書いたコードでは、
といった課題が残りますが、各論はさておき、上記のコードで示したいことは、
入力されたテキストを加工してJSONの配列にする。
JSONをパースして、JavaScript の配列を得る。
得られた配列の要素から、minimalな配列を拾い出すために再帰を使うことができる。
拾い出した minimalな配列 を分類する。
というステップを踏むのはいかがでしょうか?という考え方です。
以上、参考になれば幸いです。