กระชับสตริงแบบสอบถาม

Sep 29 2020

บทนำ

ในข่าวของแฮ็กเกอร์ John Resig คิดว่าจะเปลี่ยนข้อความค้นหา“ foo = 1 & foo = 2 & foo = 3 & blah = a & blah = b” ให้เป็นแบบนี้:“ foo = 1,2,3 & blah = a, b ", https://johnresig.com/blog/search-and-dont-replace/. เขาอ้างว่า "สั้นกว่าวิธีแก้ปัญหาของ Mark 10 บรรทัด"

สตริงการสืบค้นประกอบด้วยลำดับของคู่ชื่อ - ค่า คู่ชื่อ - ค่าประกอบด้วยชื่อและค่าคั่นด้วย = ชื่อและค่าอาจเป็นลำดับที่ว่างเปล่าของอักขระตัวเลขและตัวอักษร คู่ชื่อ - ค่าถูกคั่นด้วยอักขระ & ในลำดับ ค่าไม่ซ้ำกันสำหรับแต่ละชื่อ

ท้าทาย

สั้นกว่าน้ำยาของมาร์ค 10 บรรทัดไม่เพียงพอ

  • อ่านสตริงแบบสอบถาม
  • รวมคู่ค่าชื่อที่มีชื่อเท่ากันเป็นคู่ค่าชื่อเดียวโดยค่าที่เชื่อมต่อกันและคั่นด้วยลูกน้ำ
  • ส่งออกสตริงการสืบค้นแบบรวมโดยมีคู่ชื่อ - ค่าตามลำดับที่พบชื่อจากซ้ายไปขวาในสตริงแบบสอบถาม

นี่คือโค้ดกอล์ฟช่องโหว่มาตรฐานถูกปิด

ตัวอย่างอินพุตและเอาต์พุต

อินพุต:

foo = 1 & foo = & blah = a & foo = 3 & bar = x & blah = b & = 1 & = 2

เอาท์พุต:

foo = 1, 3 & blah = a, b & bar = x & = 1,2

อินพุต:

foo = bar & foo = foo

เอาท์พุต:

foo = bar, foo

คำตอบ

4 KevinCruijssen Oct 01 2020 at 13:34

05AB1E , 23 ไบต์

'&¡'=δ¡.¡н}εø€Ù}…,=&vyý

ลองมันออนไลน์หรือตรวจสอบกรณีทดสอบทั้งหมด

คำอธิบาย:

'&¡                     '# Split the (implicit) input-string on "&"
     δ                   # For each inner string:
   '= ¡                 '#  Split it on "="
       .¡ }              # Group all pairs by:
         н               #  Their first value
           ε             # Map over each group of pairs:
            ø            #  Zip/transpose, swapping rows/columns
             €           #  For both inner lists:
              Ù          #   Uniquify it
               }…,=&     # After the map: push string ",=&"
                    v    # Pop and loop over each character `y`:
                     yý  #  Join the inner-most list of strings with `y` as delimiter
                         # (after the loop, the result is output implicitly)

ทดลองใช้งานออนไลน์ด้วยเอาต์พุตทีละขั้นตอน

12 Arnauld Sep 29 2020 at 21:32

JavaScript (ES6),  103 99 87  86 ไบต์

บันทึก 1 ไบต์ขอบคุณ @MatthewJensen

s=>Object.values(o=/(\w*=)(\w*)/g,s.replace(o,(s,k,v)=>o[k]=o[k]?o[k]+[,v]:s)).join`&`

ลองออนไลน์!

แสดงความคิดเห็น

s =>                  // s = query string
  Object.values(      // get the values of ...
    o =               //   ... the object of this regular expression, which is
      /(\w*=)(\w*)/g, //   re-used to store the keys and values of the query
    s.replace(        //   match each key with the '=' sign and the corresponding
      o,              //   value, using the regular expression defined above
      (s, k, v) =>    //   for each matched string s, key k and value v:
        o[k] =        //     update o[k]:
          o[k] ?      //       if it's already defined:
            o[k] +    //         get the current value
            [, v]     //         append a comma, followed by v
          :           //       else:
            s         //         set it to the entire matched string
                      //         (key, '=', first value)
    )                 //   end of replace()
  ).join`&`           // end of Object.values(); join with '&'
10 lucasreta Sep 29 2020 at 20:43

JavaScript, 263 201 196 194 190 189 188 173 161 ไบต์

q=>{w={};q.split`&`.map(x=>{y=x.split`=`;if(!w[y[0]])w[y[0]]=[];w[y[0]].push(y[1])});z=`${Object.entries(w).map(a=>a=[a[0]+'='+a[1].join`,`]).join`&`}`;return z}

ลองออนไลน์

7 mschauer Sep 29 2020 at 21:46

Julia 1.0 , 106 ไบต์

f(a,z=split.(split(a,'&'),'='),u=first.(z))=join((i*'='*join(last.(z)[u.==i],',') for i in unique(u)),"&")

ลองออนไลน์!

7 HyperNeutrino Sep 29 2020 at 20:59

Python 3.8 (รุ่นก่อนวางจำหน่าย) 116 ไบต์

lambda s:(a:=[k.split("=")for k in s.split("&")])and"&".join(b+"="+",".join(d for c,d in a if c==b)for b in dict(a))

ลองออนไลน์!

-46 ไบต์ขอบคุณ ovs

-1 ไบต์ขอบคุณ Jonathan Allan (ใน Py 3.8 PR พร้อมวอลรัส)

7 Jonah Sep 29 2020 at 22:11

Ruby , 88 80 76 64 ไบต์

->s{s.scan(/(\w*=)(\w*)/).group_by(&:shift).map{|k,v|k+v*?,}*?&}

ลองออนไลน์!

-8 ไบต์ขอบคุณ ovs สำหรับการชี้ฉันสามารถกำหนด lambda ให้กับตัวแปรได้

-12 ไบต์ขอบคุณ Dingus!

5 Sisyphus Sep 30 2020 at 01:38

Python 3 , 94 ไบต์

lambda s:'&'.join(k+'='+",".join(v)for k,v in parse_qs(s,1).items())
from urllib.parse import*

ลองออนไลน์!

บางสิ่ง:

  • สิ่งนี้ใช้ได้เฉพาะเนื่องจาก Python 3.6+ รักษาลำดับพจนานุกรมตามเวลาที่แทรก เราชอบที่จะใช้ Python 2 สำหรับการนำเข้าที่สั้นกว่า ( urlparseเทียบกับurllib.parse) แต่พจนานุกรมไม่ได้เรียงลำดับอย่างถูกต้อง
  • เท่าที่ฉันชอบ f-strings k+'='+",".join(v)นั้นสั้นกว่าf'{k}={",".join(v)}'.
  • คู่.joinรู้สึกเหมือนกลิ่นกอล์ฟ แต่ฉันไม่สามารถหาวิธีที่สั้นกว่านี้ได้

Python 3 , 95 ไบต์

from urllib.parse import*
d=parse_qs(input(),1)
print('&'.join(k+'='+','.join(d[k])for k in d))

ลองออนไลน์!

5 JonathanAllan Sep 29 2020 at 21:54

เยลลี่ 28 ไบต์

-2 ขอบคุณ Zgarb!

ṣ”&ṣ€”=Ṗ€ĠṢịƲµZQ€j€”,j”=)j”&

monadic Link ยอมรับและให้รายชื่อตัวละคร

ลองออนไลน์!

อย่างไร?

ṣ”&ṣ€”=Ṗ€ĠṢịƲµZQ€j€”,j”=)j”& - Link: list of characters, S
ṣ”&                          - split at '&'s
   ṣ€”=                      - split each at '='s
                               call that A
            Ʋ                - last four links as a monad - f(A):
       Ṗ€                    -   all but last of each
         Ġ                   -   group indices by their values
          Ṣ                  -   sort (since Ġ orders by the values, not the indices)
           ị                 -   index into (A) (vectorises)
             µ          )    - for each:
              Z              -   transpose
               Q€            -   deduplicate each
                 j€”,        -   join each with ','s
                     j”=     -   join with '='s
                         j”& - join with '&'s
5 SomoKRoceS Sep 29 2020 at 22:13

05AB1E , 62 51 ไบต์

(-11 จาก @kevin)

'&¡'=δ¡D€нÙÐV_UsvYyнk©Xsèyθ',««Xs®ǝU}X妨}Yζí'=ý'&ý

ลองออนไลน์!


แนวทาง 62 ของฉัน:

'&¡ε'=¡}D€нÙ©DgÅ0Usvy¬®skDVXsèyθ',««XsYǝU}X妨}®ζεć'=s««˜}˜'&ý

คำอธิบาย:

'&¡ε'=¡}D€нÙ©DgÅ0Usvy¬®skDVXsèyθ',««XsYǝU}X妨}®ζεć'=s««˜}˜'&ý
'&¡                                                              split by &
   ε'=¡}                                                         foreach: split by =
        D                                                        duplicate
         €н                                                      foreach: push header (get the keys list)
           Ù                                                     uniquify
            ©                                                    save in register c
             Dg                                                  suplicate and get the length of that list of keys
               Å0                                                create a list of 0's with the length above
                 U                                               save in variable X
                  svy                    }                       for each set of key-value
                     ¨sk                                        find the index of that key in the keys list
                         DV                                      save the index in variable y
                           Xsè                                   get the current value of the element of X at index Y (in X we are keeping the concatenation of the values for key i)
                              yθ                                 extract the tail of the element in this iteration (a value to concatenate)
                                ',««                             concatenate with , in between
                                    XsYǝU                        update X with the new value of the element representing the key
                                          X妨}                  remove tail and head from each element of X (removing the trailing , and leading 0)
                                               ®                 push back the list of keys
                                                ζ                zip (list of keys and list of merged values)
                                                 εć'=s««˜}       foreach element in the zipped list, join with = in between such that the result is "key=values"
                                                          ˜      flat
                                                           '&ý   join with &

ลองออนไลน์!

5 Neil Sep 29 2020 at 22:41

JavaScript, 79 ไบต์

f=
s=>(s=new URLSearchParams(s)).forEach((v,k)=>s.set(k,s.getAll(k)))||unescape(s)
<input oninput=o.textContent=f(this.value)><pre id=o>

ถ้า I / O อาจเป็นสตริงการสืบค้นจริงตามข้อกำหนดของ WHATWG แทนที่จะเป็นสตริงที่ไม่ถูกต้องซึ่งดูเหมือนสตริงการสืบค้น แต่ไม่ได้เข้ารหัส URL อย่างถูกต้อง 7 ไบต์สามารถบันทึกได้โดยการกำหนดผลลัพธ์ให้เป็นสตริงแทนการไม่ใช้ค่า Escape

4 Shaggy Sep 29 2020 at 21:17

JavaScript, 106 104 76 ไบต์

พอร์ตของโซลูชัน Retina ของ Neilโพสต์โดยได้รับอนุญาต

f=q=>q==(q=q.replace(/(?<=^|&)((\w*=)[^&]*)(.*?)&\2(\w*)/,`$1,$4$3`))?q:f(q)

ลองออนไลน์!

ต้นฉบับ

การเล่นกอล์ฟที่เมาเล็กน้อยที่ฉันกลับมาทำงานอย่างมีสติ แต่ในกระบวนการนี้ได้เห็นวิธีแก้ปัญหาของ Arnauld และตระหนักว่าฉันอยู่บนเส้นทางไปสู่บางสิ่งที่เหมือนกันเกือบทั้งหมดดังนั้นฉันจึงปล่อยมันไว้

q=>Object.keys(o={},q.split`&`.map(p=>o[[k,v]=p.split`=`,k]=[...o[k]||[],v])).map(x=>x+`=`+o[x]).join`&`

ลองออนไลน์!

3 Neil Sep 30 2020 at 15:23

Retina 0.8.2 , 45 ไบต์

+1`(?<=^|&)((\w*=)[^&]*)(.*?)&\2(\w*)
$1,$4$3

ลองออนไลน์! คำอธิบาย: จับคู่คีย์ที่ซ้ำกันครั้งแรกและคีย์แรกที่ซ้ำกันซ้ำ ๆ และรวมค่ากับคีย์เดิม

3 Shaggy Sep 30 2020 at 15:52

Japt , 29 28 27 26 24 ไบต์

q& móÈk¶
ü@bøXÎîÕvÎqÃq&

ลองมัน

ที่บันทึกไว้ 2 ไบต์ขอบคุณที่ให้แรงบันดาลใจจากเควิน

(โอ้ถ้ามีเพียง Japt เท่านั้นที่มีวิธีการเฉพาะสำหรับการจัดกลุ่มแทนที่จะจัดเรียงด้วยเช่นกันอาจเป็น19 ไบต์ก็ได้)

คำอธิบาย

q& móÈk¥\nü@bøXÎîÕvÎqÃq&     :Implicit input of string U
q&                            :Split on "&"
   m                          :Map
    ó                         :  Partition after each character that returns falsey (i.e., an empty string)
     È                        :  When passed through the following function
      k                       :    Remove all characters that appear in
       ¥                      :    Literal "=="
        \n                    :Reassign to U
          ü                   :Group & sort by
           @                  :Passing each X through the following function
            b                 :  First index in U
             ø                :  That contains
              XÎ              :    First element of X
                Ã             :End grouping
                 ®            :Map each Z
                  Õ           :  Transpose
                   v          :  Map first element to
                    Î         :    Get first element
                     q        :  Join resulting array
                      Ã       :End map
                       q&     :Join with "&"

หรือเพื่อให้คำแนะนำทีละขั้นตอน:

อินพุต

"foo=1&foo=&blah=a&foo=3&bar=x&blah=b&=1&=2"

แยก

["foo=1","foo=","blah=a","foo=3","bar=x","blah=b","=1","=2"]

แผนที่และฉากกั้น

[["foo=","1"],["foo="],["blah=","a"],["foo=","3"],["bar=","x"],["blah=","b"],["=","1"],["=","2"]]

จัดกลุ่มและจัดเรียง

[[["foo=","1"],["foo="],["foo=","3"]],[["blah=","a"],["blah=","b"]],[["bar=","x"]],[["=","1"],["=","2"]]]

แผนที่และ ...

เปลี่ยน

[[["foo=","foo=","foo="],["1",null,"3"]],[["blah=","blah="],["a","b"]],[["bar="],["x"]],[["=","="],["1","2"]]]

แมปองค์ประกอบแรกกับองค์ประกอบแรก

[["foo=",["1",null,"3"]],["blah=",["a","b"]],["bar=",["x"]],["=",["1","2"]]]

เข้าร่วม

["foo=1,,3","blah=a,b","bar=x","=1,2"]

เข้าร่วม

"foo=1,,3&blah=a,b&bar=x&=1,2"
2 Noodle9 Sep 30 2020 at 11:38

อ๊าก144 \$\cdots\$144 138 ไบต์

เพิ่ม 6 ไบต์เพื่อแก้ไขข้อบกพร่อง
ที่เพิ่มเข้ามา 4 ไบต์เพื่อแก้ไขข้อผิดพลาดกรุณาชี้ให้เห็นและแก้ไขได้โดยโดมินิแวนเอสเซน
บันทึก 6 ไบต์ขอบคุณDominic van Essen !!!

BEGIN{RS="&"}{if(!(j=i[$1]++))n[m++]=$1;a[$1][j]=$2}END{for(l in n){k=n[l];o=k"=";for(j in a[k])o=o (j>0?",":"")a[k][j];printf z o;z="&"}}

ลองออนไลน์!

2 CongChen Sep 30 2020 at 13:48

R , 195 ไบต์

{Z=pryr::f
`/`=Z(a,b,el(regmatches(a,gregexpr(b,a))))
`-`=Z(a,b,paste(a,collapse=b))
Z(S,{L=S/'\\w*='
L=factor(L,unique(L))
U=tapply(S/'=\\w*',L,Z(a,trimws(a,,'=')-','))
paste0(names(U),U)-'&'})}

ลองออนไลน์!

2 valsaysReinstateMonica Sep 30 2020 at 18:15

Lua 162 ไบต์

l,t={},{}(...):gsub('(%w-)=(%w-)',load"k,v=...o=t[k]l[#l+1]=not o and k or _ t[k]=o and o..','..v or v")for i=1,#l do io.write(i>1 and'&'or'',l[i],'=',t[l[i]])end

ลองออนไลน์!

อันนี้ยาวนะฮะ อาจทำให้สั้นลงได้มากหากไม่ใช่เพื่อการสั่งซื้อ

คำอธิบาย:

l,t={},{} -- list (by first inclusion), table (keys to string)
-- (ab)use string replacement function to callback over matches in input string
(...):gsub(
    -- Match key-value pairs
    '(%w-)=(%w-)',
    -- For each pair, run callback (braces are replaced for multiline)
    load[[
        k,v=... -- Assign key, value
        o=t[k] -- Look for already stored string if any
        l[#l+1]=not o and k or _ -- If key is new, store it in list
        t[k]=o and o..','..v or v -- Append to string if it is not new, store it if it is
    ]]
)
-- For every record in list
for i=1,#l do
    -- Write with no newlines
    io.write(
        i>1 and'&'or'', -- Output & before all values but first
        l[i],'=',t[l[i]] -- Print key-value pair
    )
end
2 LegionMammal978 Oct 01 2020 at 13:02

ภาษา Wolfram (Mathematica) , 86 ไบต์

StringRiffle[Last@Reap[Sow@@@StringExtract[#,"&"->;;,"="->{2,1}],_,List],"&","=",","]&

ลองออนไลน์! ฟังก์ชัน Pure รับสตริงเป็นอินพุตและส่งคืนสตริงอื่นเป็นเอาต์พุต สิ่งนี้ได้รับแรงบันดาลใจและคล้ายกับคำตอบของ attแต่ใช้อัลกอริทึมที่คล้ายกับคำตอบในบล็อกโพสต์ (ที่นี่ใช้Sow/ Reap) นี่คือตัวอย่างของการประเมินนิพจน์ย่อยในอินพุตของ"foo=1&bar=a&foo=":

StringExtract[#,"&"->;;,"="->{2,1}] == {{"1", "foo"}, {"a", "bar"}, {"", "foo"}}
Sow@@@...                           == {"1", "a", ""}; {"1", ""} sown w/ tag "foo"; {"a"} sown w/ tag "bar"
Reap[...,_,List]                    == {{"1", "a", ""}, {{"foo", {"1", ""}}, {"bar", {"a"}}}}
Last@...                            == {{"foo", {"1", ""}}, {"bar", {"a"}}}
StringRiffle[...,"&","=",","]       == "foo=1,&bar=a"
2 GalenIvanov Oct 01 2020 at 18:37

แฟกเตอร์ 229 ไบต์

: c ( s -- s s ) 1 <hashtable> swap "&"split [ "="split ] map
[ [ dup [ last ] dip first pick push-at ] each ]
[ [ first ] map dup union ] bi dup [ [ over at ","join ] map ] dip
[ "="append ] map swap zip [ concat ] map "&"join ;

ลองออนไลน์!

มันยาว แต่ฉันค่อนข้างพอใจ :)

2 Giuseppe Sep 30 2020 at 16:00

SNOBOL4 (CSNOBOL4) , 243 221 212 ไบต์

	Q =INPUT
	T =TABLE()
N	Q (ARB '=') . L ARB . V ('&' | RPOS(0)) REM . Q	:F(O)
	T<L> =T<L> ',' V 	:(N)
O	R =CONVERT(T,'ARRAY')
I	X =X + 1
	R<X,2> ',' REM . V 	:F(P)
	O =O '&' R<X,1> V	:(I)
P	O '&' REM . OUTPUT
END

ลองออนไลน์!

TABLEใน SNOBOL นั้นแปลก มันสมบูรณ์ดียอมรับPATTERNเหมือนARBเป็นสำคัญ ''แต่ไม่สตริงที่ว่างเปล่า อย่างไรก็ตามการใช้<label>=เป็นฉลากแทนการ<label>แก้ปัญหานี้อย่างเรียบร้อย

คำอธิบายสำหรับการทำซ้ำก่อนหน้านี้:

	E =RPOS(0)					;* alias for end of string 
	A =ARB						;* alias for ARBitrary match (as short as possible)
	Q =INPUT					;* read input
	T =TABLE()					;* create a TABLE (a dictionary)
N	Q A . L '=' A . V ('&' | E) REM . Q	:F(O)	;* in regex land, this is something like
	;* '(.*=)(.*)(&|$)' where you save \1 and \2 as L and V, respectively. If there's no match, goto O
	T<L> =T<L> V ','	:(N)		;* update the values list, then goto N
O	R =CONVERT(T,'ARRAY')				;* convert T to a 2D array of [Label,Value]
I	X =X + 1					;* increment array index
	R<X,2> A . V ',' E	:F(P)			;* remove the trailing ',' from the value list. If X is out of bounds, goto P
	O =O R<X,1> V '&'	:(I)			;* Append L and V to O with an '=' and '&', then goto I
P	O A . OUTPUT '&' E				;* Print everything except for the trailing '&'
END
2 Neil Oct 09 2020 at 12:50

PHP , 146 ไบต์

<?=parse_str(str_replace('=','_[]=',$argv[1]),$a)??join('&',array_map(function($b,$c){return rtrim($b,'_').'='.join(',',$c);},array_keys($a),$a));

ลองออนไลน์! คำอธิบาย: parse_strไม่ได้ถูกออกแบบมาเพื่อจัดการค่าซ้ำ []แต่คุณสามารถชักชวนให้มันโดยการตั้งชื่อแต่ละค่าที่มีต่อท้าย นอกจากนี้ยังไม่ได้ออกแบบมาเพื่อจัดการกับชื่อที่ว่างเปล่า แต่เนื่องจากฉันกำลังต่อท้าย[]อยู่ฉันจึงสามารถเพิ่ม_เพื่อตอบสนองกรณีนั้นได้ เมื่อแยกวิเคราะห์สตริงการสืบค้นแล้วจะยังคงรวมทุกอย่างกลับเข้าด้วยกัน

1 GalenIvanov Sep 30 2020 at 11:34

สีแดง 221 ไบต์

func[s][m: copy #()s: split s"&"forall s[s/1: split s/1"="append s/1/1"="put m s/1/1
copy""]foreach v s[m/(v/1): append m/(v/1) rejoin[v/2","]]t: copy""foreach k keys-of
m[take/last m/:k repend t[k m/:k"&"]]take/last t t]

ลองออนไลน์!

มันยาวมากและฉันจะพยายามตีกอล์ฟอย่างน้อยสักหน่อย เสียดายRedไม่มีjoinฟังก์ชั่นที่สะดวก...

1 Neil Sep 30 2020 at 19:18

ถ่าน 42 ไบต์

≔E⪪S&⪪ι=θW⁻Eθ§κ⁰υ⊞υ§ι⁰⪫Eυ⁺⁺ι=⪫EΦθ¬⌕λι⊟λ,¦&

ลองออนไลน์! ลิงก์คือรหัสเวอร์ชันที่ละเอียด คำอธิบาย:

≔E⪪S&⪪ι=θ

แยกอินพุตบน&s และแยกแต่ละโทเค็นบน=s

W⁻Eθ§κ⁰υ⊞υ§ι⁰

สร้างรายการคีย์ที่ไม่ซ้ำกันตามลำดับการปรากฏตัวครั้งแรก

⪫Eυ⁺⁺ι=⪫EΦθ¬⌕λι⊟λ,¦&

สำหรับแต่ละคีย์, สารสกัดและเข้าร่วมกับค่า,, concatenate &ด้วยกุญแจและคั่นและเข้าร่วมผลโดยรวมด้วย

1 ErikF Sep 30 2020 at 05:36

C (gcc) , 319304ไบต์

ขอบคุณ ceilingcat สำหรับคำแนะนำ

ฟังก์ชันนี้จะสแกนแต่ละคู่โทเค็น (ชื่อค่า) และเพิ่มรายการสำหรับชื่อใหม่แต่ละรายการที่พบจากนั้นต่อท้ายรายการสำหรับแต่ละค่า หลังจากสร้างรายการแล้วจะวนซ้ำในแต่ละรายการและพิมพ์ค่า เพื่อประหยัดพื้นที่ฉันแบนโครงสร้างเป็นอาร์เรย์ของvoid *.

f(s,t,v,i)char*s,*t;{void*d[3]={t=0},**f,**w;for(;t=strtok(t?0:s,"&");*w=calloc(8,2),w[1]=v){t[i=strcspn(t,"=")]=0;v=t-~i;for(f=&d;strcmp(f[1]?:t,t);f=*f);for(w=f[2]=f[1]?f[2]:(f[1]=t,*f=calloc(8,5))+24;w[1];w=*w);}for(f=&d;i=*f&&printf("&%s="+!!s,f[1]);f=*f)for(w=f[2];s=*w;w=s)i=!printf(",%s"+i,w[1]);}

ลองออนไลน์!

การส่งต้นฉบับที่ไม่ใช่การเล่นกอล์ฟ:

struct list {
  struct list *next;
  char *name;
  struct list *value;
};

void f(char *s) {
  char *tok=NULL, *value;
  struct list d={}, *e, *v;
  int i;

  for(; tok=strtok(tok?NULL:s, "&"); ) {
    tok[i=strcspn(tok, "=")]=0;
    value=tok+i+1;
    for(e=&d; e->name && strcmp(e->name, tok); e=e->next);
    if(!e->name) {
      e->next=calloc(sizeof(struct list), 2);
      e->name=tok;
      e->value=e->next+1;
    }
    for(v=e->value; v->name; v=v->next);
    v->next=calloc(sizeof(struct list), 1);
    v->name=value;
  }
  for(e=&d; e->next; e=e->next, s=0) {
    printf("&%s="+!!s, e->name);
    for(v=e->value, i=1; v->next; v=v->next, i=0)
      printf(",%s"+i, v->name);
  }
}

ลองออนไลน์!

1 att Sep 30 2020 at 07:25

ภาษา Wolfram (Mathematica) , 90 88 ไบต์

StringRiffle[S=StringSplit;List@@@Normal@Merge[Rule@@@S[#~S~"&","=",2],#&],"&","=",","]&

ลองออนไลน์!

-2 ขอบคุณ LegionMammal978

S=StringSplit;
Rule@@@S[#~S~"&","=",2]         (* Convert to a list of Rules *)
Merge[ % ,#&]                   (* Combine rules into an Association, leaving values unchanged *)
Normal@ %                       (* Convert Association back into a list of Rules, *)
List@@@ %                       (* and turn Rules into Lists *)
StringRiffle[ % ,"&","=",","]   (* Concatenate, using "&", "=", and "," as separators *)
1 Chris Sep 29 2020 at 22:03

Perl 5 , -pF\&ธง73 57 ไบต์

ใช้-pF\&ในการวนซ้ำอินพุตและเปิดการแยก&อัตโนมัติ

ผลลัพธ์ที่ไม่เรียงลำดับในการแข่งขันคู่ขนาน

/=/,$z{$`}.=$z{$`}?",$'":"$`=$'"for@F;$_=join'&',values%z

ลองออนไลน์!

ใช้แฮช%zเพื่อติดตามค่าสำหรับชื่อแต่ละชื่อจากนั้นพิมพ์ออกมาทั้งหมดในตอนท้าย -16 ไบต์ขอบคุณ NahuelFouilleul

1 DominicvanEssen Sep 30 2020 at 09:26

R , 174 166 ไบต์

function(s,S=strsplit,A=sapply,P=paste,e=A(S(P(el(S(s,'&')),'=',sep=''),'='),c),n=unique(m<-e[1,]))P(n,A(n,function(x)P(e[2,m==x],collapse=',')),sep='=',collapse='&')

ลองออนไลน์!

ด้วยเหตุผลที่อธิบายไม่ได้ฉันคิดว่าความท้าทายนี้จะไม่ประสบกับการจัดการสตริงที่ละเอียดมากของR
สิ่งนี้ไม่ได้เป็นอย่างนั้นอย่างน้อยก็ขึ้นอยู่กับความพยายามของฉันจนถึงตอนนี้ ...

แสดงความคิดเห็นก่อนตีกอล์ฟ:

compactify=
function(s,                         # s = string to compactify
S=strsplit,                         # S = alias to strsplit() function
A=sapply,                           # A = alias to sapply() function
P=paste,                            # P = alias to paste() function
a=el(                               # a = the first element of ...
  S(s,'&'))                         #  ...s split on '&'
b=S(a,,'=')                         # b = each element of a, split on '='
                                    # Now, unfortunately if there's nothing after the '=',
                                    # the strsplit() function fails to add an empty string ''
                                    # so we need to do this ourselves:
e=A(b,function(x)c(x,'')            # e = for each element of b, add a '' ...  
                        [1:2])      #  ...and then take the first two elements
                                    # This gives us a 2-row matrix, with the names in row 1,
                                    # and the values in row 2
n=unique(m<-e[1,]))                 # n = unique names, m = all names of name-value pairs
m=A(n,function(x)                   # m = for each element of n...
      P(e[2,m==x],collapse=','))    #  ...paste together the values for this name, using ',' as separator
P(n,m,sep='=',collapse='&')         # Finally, paste together the pairs of elements in m, using '=' as separator...
                                    #  ...and collapse them all into one string using '&' as separator
1 Giuseppe Sep 30 2020 at 19:07

R , 162 157 151 ไบต์

function(s,S=substring)paste0(z<-unique(k<-S(x<-el(strsplit(s,"&")),1,y<-regexpr('=',x))),sapply(split(S(x,y+1),k),paste,collapse=',')[z],collapse='&')

ลองออนไลน์!

-6 ไบต์ขอบคุณ Dominic van Essen

ฟังก์ชั่นบรรทัดเดียวที่ดี ไม่พอใจ:

function(s,S=substr){
pairs <- el(strsplit(s,"&"))					# split on '&' getting list of pairs
loc <- regexpr('=',pairs)					# find location of each '=' in each pair 
keys <- substr(pairs,1,loc)					# get the key, including the '='
values <- substr(pairs,loc + 1,nchar(pairs))			# get the values (everything after '=')
unq_keys <- unique(keys)					# uniquify the keys. This retains the order.
split_vals <- split(values,keys)				# group the values into sublists by which key they are associated with
collapsed_values <- sapply(split_vals,paste,collapse=',')	# join each subgroup of values by ','
collapsed_values <- collapsed_values[unq_keys]			# and reorder them to match the order of the keys
paste0(unq_keys,collapsed_values,collapse='&')			# concatenate keys and values and join by '&'
}