Объединить два объекта в Coldfusion (используя openBD)

У меня есть следующий блок кода:

<cfset docs1 = StructNew() />
<cfset docs1['content'] = "I am" />
<cfset docs1['ida'] = "23" />
<cfset docs1['solrid'] = "23_solrid" />
<cfset docs1['title'] = "Aaaaa" />

<cfset docs2 = StructNew() />
<cfset docs2['content'] = "the most" />
<cfset docs2['ida'] = "1" />
<cfset docs2['solrid'] = "1_solrid" />
<cfset docs2['title'] = "Bbbb" />

<cfset docs3 = StructNew() />
<cfset docs3['content'] = "crap coder" />
<cfset docs3['ida'] = "7" />
<cfset docs3['solrid'] = "7_solrid" />
<cfset docs3['title'] = "Cccc" />

<cfset docs4 = StructNew() />
<cfset docs4['content'] = "in the whole universe!" />
<cfset docs4['ida'] = "39" />
<cfset docs4['solrid'] = "39_solrid" />
<cfset docs4['title'] = "Dddd" />

<cfscript> 
    doca = ArrayNew(); 
    ArrayAppend(doca, docs1); 
    ArrayAppend(doca, docs2); 
    ArrayAppend(doca, docs3); 
    ArrayAppend(doca, docs4);  
</cfscript>  

<cfset forsolr1 = StructNew()>
<cfset forsolr1['docs'] = doca>
<cfset forext1 = SerializeJson(forsolr1)>

<cfdump var="#forsolr1#" label="Struct1">
<cfoutput>
    #forext1#
</cfoutput>
<br /><br /><br />


<cfset docsh = StructNew() />
<cfset docsh['23_solrid'] = "I need" />
<cfset docsh['1_solrid'] = "to read" />
<cfset docsh['7_solrid'] = "a lot of" />
<cfset docsh['39_solrid'] = "programming books!" />

<cfset i = 1>
<cfset solrid = "solrid">
<cfset result = ArrayNew(1)>

<cfloop collection="#docsh#" item="key" >
  <cfset innerstruct = StructNew()>
  <cfset innerstruct['solrid'] = #key#>
  <cfset innerstruct['dochighlighted'] = #docsh[key]#>
  <cfset result[i] = innerstruct>
  <cfset i = i + 1>
</cfloop>

<cfset forsolr = StructNew()>
<cfset forsolr['docs'] = result>
<cfset forext = SerializeJson(forsolr)>

<cfdump var="#forsolr#" label="Struct2">
<cfoutput>
    #forext#
</cfoutput>

Результатом являются два объекта(структура массива структур):

Первый объект

{
   "docs":[
      {
         "content":"I am",
         "ida":"23",
         "solrid":"23_solrid",
         "title":"Aaaaa"
      },
      {
         "content":"the most",
         "ida":"1",
         "solrid":"1_solrid",
         "title":"Bbbb"
      },
      {
         "content":"crap coder",
         "ida":"7",
         "solrid":"7_solrid",
         "title":"Cccc"
      },
      {
         "content":"in the whole universe!",
         "ida":"39",
         "solrid":"39_solrid",
         "title":"Dddd"
      }
   ]
}

Второй объект

{
   "docs":[
      {
         "solrid":"23_solrid",
         "dochighlighted":"I need"
      },
      {
         "solrid":"1_solrid",
         "dochighlighted":"to read"
      },
      {
         "solrid":"7_solrid",
         "dochighlighted":"a lot of"
      },
      {
         "solrid":"39_solrid",
         "dochighlighted":"programming books!"
      }
   ]
}

Можно ли объединить эти два объекта в один в виде (копировать второй в первый):

{
   "docs":[
      {
         "content":"I am",
         "ida":"23",
         "solrid":"23_solrid",
         "title":"Aaaaa",
         "dochighlighted":"I need"
      },
      {
         "content":"the most",
         "ida":"1",
         "solrid":"1_solrid",
         "title":"Bbbb",
         "dochighlighted":"to read"
      },
      {
         "content":"crap coder",
         "ida":"7",
         "solrid":"7_solrid",
         "title":"Cccc",
         "dochighlighted":"a lot of"
      },
      {
         "content":"in the whole universe!",
         "ida":"39",
         "solrid":"39_solrid",
         "title":"Dddd",
         "dochighlighted":"programming books!"
      }
   ]
}

Я пробовал функцию structAppend безрезультатно. Эта функция не может добавлять глубоко вложенные элементы. Можно ли сохранить порядок? Причина этого в том, что вышеперечисленные объекты являются результатами поисковой системы, поэтому очень важно сохранить первоначальный порядок. Можно ли объединить два объекта по ключевой ссылке? Причина, по которой я спрашиваю, заключается в том, что первый объект выходит из поисковой системы в определенном порядке (обратите внимание на solrid), а второй объект не может. Пример:

 *First object*

{
   "docs":[
      {
         "content":"I am",
         "ida":"23",
         "solrid":"23_solrid",
         "title":"Aaaaa"
      },
      {
         "content":"the most",
         "ida":"1",
         "solrid":"1_solrid",
         "title":"Bbbb"
      },
      {
         "content":"crap coder",
         "ida":"7",
         "solrid":"7_solrid",
         "title":"Cccc"
      },
      {
         "content":"in the whole universe!",
         "ida":"39",
         "solrid":"39_solrid",
         "title":"Dddd"
      }
   ]
}

 *Second object*

{
   "docs":[
      {
         "solrid":"39_solrid",
         "dochighlighted":"programming books!"
      },
      {

         "solrid":"7_solrid",
         "dochighlighted":"a lot of"
      },
      {
         "solrid":"1_solrid",
         "dochighlighted":"to read"
      },
      {
         "solrid":"23_solrid",
         "dochighlighted":"I need"
      }
   ]
}

Можно ли добиться такого же результата объединения, как описано выше?

{
   "docs":[
      {
         "content":"I am",
         "ida":"23",
         "solrid":"23_solrid",
         "title":"Aaaaa",
         "dochighlighted":"I need"
      },
      {
         "content":"the most",
         "ida":"1",
         "solrid":"1_solrid",
         "title":"Bbbb",
         "dochighlighted":"to read"
      },
      {
         "content":"crap coder",
         "ida":"7",
         "solrid":"7_solrid",
         "title":"Cccc",
         "dochighlighted":"a lot of"
      },
      {
         "content":"in the whole universe!",
         "ida":"39",
         "solrid":"39_solrid",
         "title":"Dddd",
         "dochighlighted":"programming books!"
      }
   ]
}

Огромное спасибо,

С честью,

Том

Греция


person Community    schedule 05.08.2012    source источник
comment
Слишком. много. код. Как вы думаете, вы можете обобщить свой вопрос и сократить его до 10-й части исходного размера?   -  person Tomalak    schedule 06.08.2012
comment
@Tomalak Привет, код не имеет значения. Это просто для справки. Как вы думаете, включение этих «спагетти» сделает пост утомительным?   -  person    schedule 06.08.2012
comment
Да, это немного. Из того, что я вижу, вы спрашиваете, как объединить две простые структуры.   -  person Tomalak    schedule 06.08.2012


Ответы (1)


Это должно продвинуть вас довольно далеко:

<cffunction name="ArrayOfStructsMerge" returntype="array" access="public" output="yes">
  <cfargument name="left"  type="array"  required="yes">
  <cfargument name="right" type="array"  required="yes">
  <cfargument name="id"    type="string" required="yes">

  <cfset var result = Duplicate(arguments.left)>
  <cfset var element = "">
  <cfset var key = "">
  <cfset var currentId = "">
  <cfset var lookup = StructNew()>

  <cfloop array="#result#" index="element">
    <cfif IsStruct(element) and StructKeyExists(element, arguments.id)>
      <cfset currentId = element[arguments.id]>
      <cfset lookup[currentId] = element>
    </cfif>
  </cfloop>

  <cfloop array="#arguments.right#" index="element">
    <cfif IsStruct(element) and StructKeyExists(element, arguments.id)>
      <cfset currentId = element[arguments.id]>
      <cfif StructKeyExists(lookup, currentId)>
        <cfloop collection="#element#" item="key">
          <cfset lookup[currentId][key] = Duplicate(element[key])>
        </cfloop>
      <cfelse>
        <cfset ArrayAppend(result, Duplicate(element))>
      </cfif>
    </cfif>
  </cfloop>

  <cfreturn result>
</cffunction>

Он работает неразрушающе (без изменения исходных объектов). Назовите это так:

<cfset result = ArrayOfStructsMerge(obj1.docs, obj2.docs, "solrid")>
<cfdump var="#result#">

<cfset a1 = [{id: 1, a: "a1"}, {id: 2, a: "a2"}, {id: 4, d: "d4"}]>
<cfset a2 = [{id: 1, a: "a1-new"}, {id: 2, b: "b2"}, {id: 3, c: "c3"}]>
<cfset a3 = ArrayOfStructsMerge(a1, a2, "id")>

Результат слияния массивов()

person Tomalak    schedule 05.08.2012
comment
@ Томалак. Спасибо за ответ. Я проверил ваш код, и он не работает. что-то не так с index=i в циклах. Я не могу найти, что происходит не так, потому что я новичок. Любая помощь будет принята с благодарностью. Том - person ; 06.08.2012
comment
@anarchos78 Функция исправлена. Я перепутал воспоминания о <cfloop array="...">. - person Tomalak; 06.08.2012
comment
Я не знаю, как отблагодарить вас. Ваш ответ был аналитическим. Отличная работа. Недурно. Последний вопрос: что именно мне нужно сделать, чтобы достичь ваших навыков программирования? С честью. Том - person ; 06.08.2012
comment
@anarchos78 Спасибо, это очень любезно. -- У меня почти 20 лет опыта, вот и все. Так что я думаю, что вы должны сделать, это сохранить его. ;) - person Tomalak; 06.08.2012