জাভাস্ক্রিপ্টে একাধিক অ্যারের কার্টেসিয়ান পণ্য


111

আপনি কীভাবে জাভাস্ক্রিপ্টে একাধিক অ্যারের কার্টেসিয়ান পণ্যটি প্রয়োগ করবেন?

উদাহরণ হিসাবে,

cartesian([1, 2], [10, 20], [100, 200, 300]) 

ফিরে আসা উচিত

[
  [1, 10, 100],
  [1, 10, 200],
  [1, 10, 300],
  [2, 10, 100],
  [2, 10, 200]
  ...
]


3
এটি js-combinatorics মডিউলে প্রয়োগ করা হয়েছে: github.com/dankogai/js-combinatorics
সেগাল-হালেভি


আমি আন্ডারস্কোর.জেএস সম্পর্কে একমত, তবে আমি নিশ্চিত নই যে ফাংশনাল-প্রোগ্রামিং ট্যাগটি সরানো কীভাবে @le_m
ভাইবেল

Fww, d3 d3.cross(a, b[, reducer])ফেব্রুয়ারিতে যুক্ত করা হয়েছে। github.com/d3/d3-array#cross
Toph

উত্তর:


105

2017 আপডেট: ভ্যানিলা জেএস সহ 2-লাইনের উত্তর

এখানে সমস্ত উত্তর অত্যধিক জটিল , তাদের বেশিরভাগই 20 লাইন কোড বা তারও বেশি সময় নেয়।

এই উদাহরণটিতে ভ্যানিলা জাভাস্ক্রিপ্টের মাত্র দুটি লাইন ব্যবহার করা হয়েছে , কোনও লড্যাশ, আন্ডারস্কোর বা অন্যান্য গ্রন্থাগার নেই:

let f = (a, b) => [].concat(...a.map(a => b.map(b => [].concat(a, b))));
let cartesian = (a, b, ...c) => b ? cartesian(f(a, b), ...c) : a;

হালনাগাদ:

এটি উপরের মতো একই তবে এয়ারবিএনবি জাভাস্ক্রিপ্ট স্টাইল গাইডটি কঠোরভাবে অনুসরণ করতে উন্নত হয়েছে - এসলিন্ট-কনফিগারেশন-এয়ারবিএনবি-বেসের সাথে ESLint ব্যবহার করে যাচাই করা হয়েছে :

const f = (a, b) => [].concat(...a.map(d => b.map(e => [].concat(d, e))));
const cartesian = (a, b, ...c) => (b ? cartesian(f(a, b), ...c) : a);

আসল কোড সহ লিন্টারের সমস্যা সম্পর্কে আমাকে জানানোর জন্য ZuBB কে বিশেষ ধন্যবাদ ।

উদাহরণ

এটি আপনার প্রশ্নের সঠিক উদাহরণ:

let output = cartesian([1,2],[10,20],[100,200,300]);

আউটপুট

এটি সেই আদেশের আউটপুট:

[ [ 1, 10, 100 ],
  [ 1, 10, 200 ],
  [ 1, 10, 300 ],
  [ 1, 20, 100 ],
  [ 1, 20, 200 ],
  [ 1, 20, 300 ],
  [ 2, 10, 100 ],
  [ 2, 10, 200 ],
  [ 2, 10, 300 ],
  [ 2, 20, 100 ],
  [ 2, 20, 200 ],
  [ 2, 20, 300 ] ]

ডেমো

ডেমো এতে দেখুন:

বাক্য গঠন

আমি এখানে যে বাক্য গঠন ব্যবহার করেছি তা নতুন কিছু নয়। আমার উদাহরণটি স্প্রেড অপারেটর এবং বাকী প্যারামিটারগুলি ব্যবহার করে - জাভাস্ক্রিপ্টের বৈশিষ্ট্যগুলি জুন 2015 এ প্রকাশিত ECMA-262 স্ট্যান্ডার্ডের 6th ষ্ঠ সংস্করণে সংজ্ঞায়িত হয়েছে এবং এর আগে অনেক উন্নত হয়েছে, ES6 বা ES2015 হিসাবে বেশি পরিচিত। দেখা:

এটি এই জাতীয় কোডটিকে এত সহজ করে তোলে যে এটি ব্যবহার না করা একটি পাপ। পুরানো প্ল্যাটফর্মগুলির জন্য যা এটিকে স্থানীয়ভাবে সমর্থন করে না আপনি সর্বদা এটি পুরানো বাক্য গঠনতে ট্র্যাপিলেস করার জন্য বাবেল বা অন্যান্য সরঞ্জাম ব্যবহার করতে পারেন - এবং বাস্তবে বাবেলের দ্বারা প্রতিস্থাপন করা আমার উদাহরণটি এখানে বেশিরভাগ উদাহরণের চেয়ে এখনও ছোট এবং সরল, তবে এটি হয় না প্রকৃতপক্ষে গুরুত্বপূর্ণ কারণ প্রতিস্থাপনের আউটপুট এমন কিছু নয় যা আপনার বোঝার বা বজায় রাখা দরকার, এটি কেবল একটি সত্য যে আমি আকর্ষণীয় পেয়েছি।

উপসংহার

কোডের শত শত লাইন লেখার দরকার নেই যা রক্ষণাবেক্ষণ করা শক্ত এবং এত সহজ জিনিসের জন্য পুরো লাইব্রেরি ব্যবহার করার দরকার নেই, যখন ভ্যানিলা জাভাস্ক্রিপ্টের দুটি লাইন খুব সহজেই কাজটি সম্পন্ন করতে পারে। আপনি দেখতে পাচ্ছেন যে এটি ভাষার আধুনিক বৈশিষ্ট্যগুলি ব্যবহার করতে সত্যিই অর্থ প্রদান করে এবং যেখানে আপনি আধুনিক বৈশিষ্ট্যগুলির কোনও নেটিভ সমর্থন না করে প্রত্নতাত্ত্বিক প্ল্যাটফর্মগুলি সমর্থন করতে চান আপনি সর্বদা নতুন সিনট্যাক্সটিকে পুরানোটির সাথে স্থানান্তরিত করতে বাবেল বা অন্যান্য সরঞ্জাম ব্যবহার করতে পারেন ।

1995 এর মতো কোড করবেন না

জাভাস্ক্রিপ্ট বিকশিত হয় এবং এটি একটি কারণে এটি করে। টিসি 39 নতুন বৈশিষ্ট্য যুক্ত করার সাথে ভাষা নকশার একটি আশ্চর্যজনক কাজ করে এবং ব্রাউজার বিক্রেতারা সেই বৈশিষ্ট্যগুলি বাস্তবায়নের জন্য আশ্চর্যজনক কাজ করে।

ব্রাউজারগুলিতে প্রদত্ত যে কোনও বৈশিষ্ট্যটির দেশীয় সমর্থনের বর্তমান অবস্থা দেখতে, দেখুন:

নোড সংস্করণে সমর্থনটি দেখতে, দেখুন:

প্ল্যাটফর্মগুলিতে আধুনিক সিনট্যাক্স ব্যবহার করতে যা এটি স্থানীয়ভাবে সমর্থন করে না, ব্যাবেল ব্যবহার করুন:


যেভাবে টাইপস্ক্রিপ্ট অ্যারে ছড়িয়ে পড়ে তার জন্য অ্যাকাউন্টে সামান্য পরিবর্তন সহ একটি টাইপস্ক্রিপ্ট সংস্করণ এখানে। gist.github.com/ssippe/1f92625532eef28be6974f898efb23ef
স্যাম সিপ্পি

1
@rsp সত্যিই ভাল উত্তরের জন্য অনেক ধন্যবাদ। যদিও আমি আপনাকে ছায়াময় ভেরিয়েবল (২ টি স্থানীয় ab
ভার

7
"এটি 1995 এর মতো কোড করবেন না" - অপ্রীতিকর হওয়ার দরকার নেই, সবাই এখনও ধরা পড়ে না।
গডওহ্যাকার

7
এটি জরিমানা হয় যখন খাওয়ানো হয় ['a', 'b'], [1,2], [[9], [10]]যা ফলন করবে[ [ 'a', 1, 9 ], [ 'a', 1, 10 ], [ 'a', 2, 9 ], [ 'a', 2, 10 ], [ 'b', 1, 9 ], [ 'b', 1, 10 ], [ 'b', 2, 9 ], [ 'b', 2, 10 ] ]ফলশ্রুতিতে ফলস্বরূপ ফলস্বরূপ । মানে আমি আইটেমের ধরণ রাখব না [[9], [10]]
রেডু

1
যেহেতু আমরা ...ইতিমধ্যে ব্যবহার করছি , [].concat(...[array])সহজ হয়ে উঠা উচিত নয় [...array]?
লাজার লজুবেনভীć

88

এখানে সমস্যার কোনও কার্যকরী সমাধান (কোনও পরিবর্তনীয় ভেরিয়েবল ছাড়াই !) ব্যবহার করে reduceএবং flattenসরবরাহিত রয়েছে underscore.js:

function cartesianProductOf() {
    return _.reduce(arguments, function(a, b) {
        return _.flatten(_.map(a, function(x) {
            return _.map(b, function(y) {
                return x.concat([y]);
            });
        }), true);
    }, [ [] ]);
}

// [[1,3,"a"],[1,3,"b"],[1,4,"a"],[1,4,"b"],[2,3,"a"],[2,3,"b"],[2,4,"a"],[2,4,"b"]]
console.log(cartesianProductOf([1, 2], [3, 4], ['a']));  
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore.js"></script>

মন্তব্য: এই সমাধানটি অনুপ্রাণিত হয়েছিল http://cwestblog.com/2011/05/02/cartesian-product-of-m Multipleple-arrays/


এই উত্তরে একটি টাইপো রয়েছে, সেখানে "সত্য" হওয়া উচিত নয় (সম্ভবত আপনি এই পোস্টটি তৈরি করার পরে লোডাশ বদলেছে?)
ক্রিস জেফারসন

ক্রিস জেফারসনের দ্বিতীয় পরম হ'ল চ্যাপ্টা flattenঅগভীর করা। এটি এখানে বাধ্যতামূলক!
ভাইবল

4
দুঃখিত, এটি একটি লড্যাশ / আন্ডারস্কোর বেমানান, তারা পতাকাটির চারপাশে অদলবদল করে।
ক্রিস জেফারসন

1
সুতরাং যখন সমরূপতার, ব্যবহার trueসঙ্গে আন্ডারস্কোর ও ব্যবহার falseদিয়ে lodash অগভীর সমরূপতার নিশ্চিত করতে হবে।
আকসেলি পালান

কীভাবে এই ফাংশনটি সংশোধন করবেন যাতে এটি অ্যারের অ্যারে গ্রহণ করে?

44

এখানে কোনও লাইব্রেরি ব্যবহার না করে সরল জাভাস্ক্রিপ্টে @ ভাইবেলের কোডের একটি সংশোধিত সংস্করণ রয়েছে:

function cartesianProduct(arr) {
    return arr.reduce(function(a,b){
        return a.map(function(x){
            return b.map(function(y){
                return x.concat([y]);
            })
        }).reduce(function(a,b){ return a.concat(b) },[])
    }, [[]])
}

var a = cartesianProduct([[1, 2,3], [4, 5,6], [7, 8], [9,10]]);
console.log(JSON.stringify(a));


2
কার্টেসিয়ান প্রোডাক্ট ([[[1], [2], [3]]], ['ক', 'বি'], [['গামা'], [['আলফা']]], ['জিআইআই, 'ফা']]) যেমন এটি ['গামা'] থেকে 'গামা' এবং [['আলফা']] থেকে '' আলফা ']
ফ্ল্যাট করে

.concat(y)পরিবর্তে কারণ.concat([ y ])
আপনাকে ধন্যবাদ

@ থ্যাঙ্কিউ আপনি মন্তব্য করার পরিবর্তে সরাসরি উত্তরটি সম্পাদনা করতে পারেন, এখনই এটির দরকার নেই: পি
অলিভিয়ার লালনডে

28

মনে হয় সম্প্রদায়টি এটিকে তুচ্ছ এবং একটি রেফারেন্স বাস্তবায়ন সহজেই বলে মনে করে, সংক্ষিপ্ত পরিদর্শন করার পরে আমি না পারতাম বা সম্ভবত এটিই ঠিক যে আমি চাকাটি পুনরায় উদ্ভাবন করা বা শ্রেণিকক্ষের মতো প্রোগ্রামিংয়ের সমস্যাগুলি সমাধান করার মতোই হোক না কেন এটি আপনার ভাগ্যবান দিন way :

function cartProd(paramArray) {

  function addTo(curr, args) {

    var i, copy, 
        rest = args.slice(1),
        last = !rest.length,
        result = [];

    for (i = 0; i < args[0].length; i++) {

      copy = curr.slice();
      copy.push(args[0][i]);

      if (last) {
        result.push(copy);

      } else {
        result = result.concat(addTo(copy, rest));
      }
    }

    return result;
  }


  return addTo([], Array.prototype.slice.call(arguments));
}


>> console.log(cartProd([1,2], [10,20], [100,200,300]));
>> [
     [1, 10, 100], [1, 10, 200], [1, 10, 300], [1, 20, 100], 
     [1, 20, 200], [1, 20, 300], [2, 10, 100], [2, 10, 200], 
     [2, 10, 300], [2, 20, 100], [2, 20, 200], [2, 20, 300]
   ]

সম্পূর্ণ রেফারেন্স বাস্তবায়ন যে তুলনামূলকভাবে দক্ষ ... :- ডি

দক্ষতার উপর: আপনি লুপটি বাইরে নিয়ে গিয়ে এবং পৃথকভাবে দুটি পৃথক লুপ রেখে কিছু অর্জন করতে পারেন যেহেতু এটি প্রযুক্তিগতভাবে ধ্রুবক এবং আপনি শাখার পূর্বাভাস এবং সমস্ত জগাখিচুড়ি দিয়ে সহায়তা করছেন তবে জাভাস্ক্রিপ্টে এই বিন্দুটি একরকম

যাইহোক, উপভোগ করুন


1
আপনার বিস্তারিত উত্তরের জন্য ধন্যবাদ @ কেকোজ আপনি reduceঅ্যারের ফাংশনটি ব্যবহার করবেন না কেন ?
ভাইবেল

1
@ ভাইবেল আপনি হ্রাস কেন ব্যবহার করতে চান? একটির জন্য, পুরানো ব্রাউজারগুলির জন্য হ্রাসের খুব দুর্বল সমর্থন রয়েছে (দেখুন: বিকাশকারী.মোজিলা.আর.ইন.ইউএস / ডকস / জাভা স্ক্রিপ্ট / রেফারেন্স/… ) এবং যে কোনও ক্ষেত্রে সেই উত্তরটির সেই ক্রেজি কোডটি আসলে আপনাকে পঠনযোগ্য বলে মনে হচ্ছে? ? এটা আমার কাছে নেই নিশ্চিত যে এটি সংক্ষিপ্ত, তবে একবার এই কোডটি একই দৈর্ঘ্যের প্রায় কাছাকাছি হবে, ডিবাগ করা / অনুকূলিতকরণ করা সহজ, দ্বিতীয়ত এই সমস্ত "হ্রাস" সমাধান একই জিনিসে ভেঙে যায়, যদি না তাদের ক্লোজার লুক (তাত্ত্বিকভাবে ধীর) হয় তবে এটি আরও শক্ত ডিজাইন করতে যাতে এটি অসীম সেটগুলি পরিচালনা করে ...
ckozl

5
আমি একটি 2+ বার দ্রুত এবং (imo) ক্লিনার সংস্করণ তৈরি করেছি: পেস্টবিন.com / ওয়াইবিজিকিউফ 7 এটি ব্যবহার না করে result = result.concat(...)এবং ব্যবহার না করে গতি বাড়িয়ে তোলেargs.slice(1) । দুর্ভাগ্যক্রমে, আমি পরিত্রাণ পাওয়ার উপায় curr.slice()এবং পুনরাবৃত্তি খুঁজে পাচ্ছিলাম না ।
পৌন

2
@ পউন সুন্দর কাজ, আমি যা দেখছি তার উপর ভিত্তি করে 10% -50% পারফরম্যান্স বৃদ্ধির লিগে লিগের পুরোপুরি হট স্পটগুলিতে দুর্দান্ত হ্রাস। যদিও আমি "পরিষ্কার-পরিচ্ছন্নতা" হিসাবে কথা বলতে পারি না, আমার মনে হয় ক্লোজার স্কোপ ভেরিয়েবল ব্যবহারের কারণে আপনার সংস্করণটি অনুসরণ করা আসলে আরও বেশি কঠিন। তবে সাধারণভাবে বলতে গেলে আরও পারফরম্যান্ট কোড অনুসরণ করা শক্ত। আমি পঠনযোগ্যতার জন্য মূল সংস্করণটি লিখেছি, আমি আশা করি আমার আরও বেশি সময় থাকি যাতে আমি আপনাকে একটি ছড়িয়ে দেওয়া পারফরম্যান্সে নিযুক্ত করতে পারি;) সম্ভবত পরে ...
ckozl

এটি সত্যিই সেই সমস্যাগুলির মধ্যে একটি
জেমস

26

নিম্নলিখিত দক্ষ জেনারেটর ফাংশন সমস্ত প্রদত্ত পুনরাবৃত্তের কার্টেসিয়ান পণ্য প্রদান করে :

// Generate cartesian product of given iterables:
function* cartesian(head, ...tail) {
  const remainder = tail.length > 0 ? cartesian(...tail) : [[]];
  for (let r of remainder) for (let h of head) yield [h, ...r];
}

// Example:
console.log(...cartesian([1, 2], [10, 20], [100, 200, 300]));

এটি অ্যারে, স্ট্রিং, সেটগুলি এবং পুনরাবৃত্ত প্রোটোকল প্রয়োগকারী অন্যান্য সমস্ত সামগ্রী গ্রহণ করে ।

এন-অ্যারি কার্টেসিয়ান পণ্য যা দেয় তার স্পেসিফিকেশন অনুসরণ করে

  • []যদি এক বা একাধিক প্রদত্ত পুনরাবৃত্তি খালি থাকে, যেমন []বা''
  • [[a]]যদি একক মান সহ একক পুনরাবৃত্তি aদেওয়া হয়।

অন্যান্য পরীক্ষাগুলি প্রত্যাশিত হিসাবে নিম্নলিখিত পরীক্ষার কেস দ্বারা প্রদর্শিত হিসাবে পরিচালনা করা হয়:


এই কি ঘটছে তা বোঝাতে আপনার আপত্তি আছে? অনেক ধন্যবাদ!
LeandroP

জেনারেটর ফাংশন + লেজ পুনরাবৃত্তি + ডাবল-স্তর লুপগুলি ব্যবহার করার একটি দুর্দান্ত চমত্কার উদাহরণ আমাদের শেখানোর জন্য ধন্যবাদ! তবে আউটপুট সাব-অ্যারেগুলির ক্রমটি সঠিক করতে কোডের মধ্যে প্রথম লুপের অবস্থান পরিবর্তন করা দরকার। স্থির কোড:function* cartesian(head, ...tail) { for (let h of head) { const remainder = tail.length > 0 ? cartesian(...tail) : [[]]; for (let r of remainder) yield [h, ...r] } }
ooo

@ooo আপনি যদি ওপির মন্তব্যে দেওয়া কার্টেসিয়ান পণ্য টিপলগুলির ক্রম পুনরায় উত্পাদন করতে চান তবে আপনার পরিবর্তনটি সঠিক mod তবে, পণ্যের মধ্যে টিউপসগুলির ক্রম সাধারণত প্রাসঙ্গিক হয় না, যেমন গাণিতিকভাবে ফলাফলটি একটি আনর্ডার্ড সেট। আমি এই অর্ডারটি বেছে নিয়েছি কারণ এর জন্য অনেক কম পুনরাবৃত্তি কল প্রয়োজন এবং অতএব এটি আরও কিছুটা পারফরম্যান্ট - যদিও আমি একটি বেঞ্চমার্ক চালাত না।
লে_ম

এরেটাম: উপরের আমার মন্তব্যে "লেজ পুনরাবৃত্তি" "পুনরাবৃত্তি" হওয়া উচিত (এই ক্ষেত্রে কোনও লেজ কল নয়)।
ooo

20

এখানে একটি অ-অভিনব, সোজা পুনরাবৃত্তি সমাধান:

function cartesianProduct(a) { // a = array of array
    var i, j, l, m, a1, o = [];
    if (!a || a.length == 0) return a;

    a1 = a.splice(0, 1)[0]; // the first array of a
    a = cartesianProduct(a);
    for (i = 0, l = a1.length; i < l; i++) {
        if (a && a.length) for (j = 0, m = a.length; j < m; j++)
            o.push([a1[i]].concat(a[j]));
        else
            o.push([a1[i]]);
    }
    return o;
}

console.log(cartesianProduct([[1,2], [10,20], [100,200,300]]));
// [[1,10,100],[1,10,200],[1,10,300],[1,20,100],[1,20,200],[1,20,300],[2,10,100],[2,10,200],[2,10,300],[2,20,100],[2,20,200],[2,20,300]]


2
এটি এই বিষয়টির অধীনে সর্বাধিক দক্ষ খাঁটি জেএস কোড হিসাবে পরিণত হয়েছে। দৈর্ঘ্য 1M এর অ্যারে উত্পাদন করতে 3 x 100 আইটেম অ্যারে সমাপ্ত করতে 600 ডলারের সেকেন্ডের মতো লাগে।
রেডু

1
কার্টেসিয়ান প্রোডাক্ট ([[[1], [2], [3]]], ['এ', 'বি'], [['গামা'], [[আলফা ']]], [' জিআইআই ', 'FAA']]); মূল মানগুলি
সমতল না করে

10

এখানে একটি পুনরাবৃত্ত উপায় যা ECMAScript 2015 জেনারেটর ফাংশন ব্যবহার করে যাতে আপনাকে একবারে সমস্ত টিপল তৈরি করতে হবে না:

function* cartesian() {
    let arrays = arguments;
    function* doCartesian(i, prod) {
        if (i == arrays.length) {
            yield prod;
        } else {
            for (let j = 0; j < arrays[i].length; j++) {
                yield* doCartesian(i + 1, prod.concat([arrays[i][j]]));
            }
        }
    }
    yield* doCartesian(0, []);
}

console.log(JSON.stringify(Array.from(cartesian([1,2],[10,20],[100,200,300]))));
console.log(JSON.stringify(Array.from(cartesian([[1],[2]],[10,20],[100,200,300]))));


যখন কোনও অ্যারেতে অ্যারের আইটেম থাকে তখন এটি কাজ করবে নাcartesian([[1],[2]],[10,20],[100,200,300])
রেডু

অ্যারে যুক্তি সমর্থন করার জন্য @ রেডু উত্তর আপডেট করা হয়েছে।
হেনিনী

হ্যাঁ .concat()স্প্রেড অপারেটরে অন্তর্নির্মিত কখনও কখনও প্রতারণামূলক হয়ে উঠতে পারে।
রেডু

10

দেশীয় ES2019 ব্যবহার করে এখানে একটি ওয়ান-লাইনার দেওয়া হয়েছে flatMap। কোনও লাইব্রেরির প্রয়োজন নেই, কেবলমাত্র একটি আধুনিক ব্রাউজার (বা ট্রান্সপোর্টার):

data.reduce((a, b) => a.flatMap(x => b.map(y => [...x, y])), [[]]);

এটি মূলত ভিডাবলির উত্তরের একটি আধুনিক সংস্করণ, লোটাস ছাড়াই।


9

ES6 জেনারেটরের সাথে একটি সাধারণ ব্যাকট্র্যাকিং ব্যবহার করে,

function cartesianProduct(...arrays) {
  let current = new Array(arrays.length);
  return (function* backtracking(index) {
    if(index == arrays.length) yield current.slice();
    else for(let num of arrays[index]) {
      current[index] = num;
      yield* backtracking(index+1);
    }
  })(0);
}
for (let item of cartesianProduct([1,2],[10,20],[100,200,300])) {
  console.log('[' + item.join(', ') + ']');
}
div.as-console-wrapper { max-height: 100%; }

নীচে পুরানো ব্রাউজারগুলির সাথে সামঞ্জস্যপূর্ণ একই সংস্করণ রয়েছে।


9

এটি তীর ফাংশন ব্যবহার করে একটি খাঁটি ES6 সমাধান

function cartesianProduct(arr) {
  return arr.reduce((a, b) =>
    a.map(x => b.map(y => x.concat(y)))
    .reduce((a, b) => a.concat(b), []), [[]]);
}

var arr = [[1, 2], [10, 20], [100, 200, 300]];
console.log(JSON.stringify(cartesianProduct(arr)));


7

লোডাশ সহ একটি কফিসিপি সংস্করণ:

_ = require("lodash")
cartesianProduct = ->
    return _.reduceRight(arguments, (a,b) ->
        _.flatten(_.map(a,(x) -> _.map b, (y) -> x.concat(y)), true)
    , [ [] ])

7

ইনডেন্টেশন সহ আরও ভাল পড়ার জন্য একটি একক লাইন পদ্ধতির।

result = data.reduce(
    (a, b) => a.reduce(
        (r, v) => r.concat(b.map(w => [].concat(v, w))),
        []
    )
);

এটি চাওয়া কার্টেসিয়ান আইটেমগুলির অ্যারে সহ একক অ্যারে নেয়।

var data = [[1, 2], [10, 20], [100, 200, 300]],
    result = data.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));

console.log(result.map(a => a.join(' ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }


অ্যারেতে একক উপাদান রয়েছে এমন ক্ষেত্রে সঠিকভাবে পরিচালনা করতে আমাকে একটি প্রহরী বিবৃতি যোগ করতে হয়েছিল:if (arr.length === 1) return arr[0].map(el => [el]);
জ্যাকবএভলিন

5

এটি ফাংশনাল-প্রোগ্রামিং ট্যাগ করা হয় তাই আসুন তালিকা monad একবার দেখুন :

এই monadic তালিকার জন্য একটি অ্যাপ্লিকেশন হ'ল nondeteristic গণনা উপস্থাপন। একটি অ্যালগরিদমে List সমস্ত মৃত্যুদন্ডের জন্য ফলাফল ধরে রাখতে পারে ...

ওয়েল এটি জন্য নিখুঁত ফিট মত শোনাচ্ছে cartesian। জাভাস্ক্রিপ্ট আমাদের দেয় Arrayএবং মোনাদিক বাইন্ডিং ফাংশন Array.prototype.flatMap, তাই আসুন এগুলি ব্যবহারের জন্য রাখি -

const cartesian = (...all) =>
{ const loop = (t, a, ...more) =>
    a === undefined
      ? [ t ]
      : a .flatMap (x => loop ([ ...t, x ], ...more))
  return loop ([], ...all)
}

console .log (cartesian ([1,2], [10,20], [100,200,300]))

loopউপরের পরিবর্তে , tএকটি তরকারি প্যারামিটার হিসাবে যুক্ত করা যেতে পারে -

const makeCartesian = (t = []) => (a, ...more) =>
  a === undefined
    ? [ t ]
    : a .flatMap (x => makeCartesian ([ ...t, x ]) (...more))

const cartesian =
  makeCartesian ()

console .log (cartesian ([1,2], [10,20], [100,200,300]))


3

এই ইনপুট অ্যারেগুলির মধ্যে কোনও অ্যারে আইটেম থাকলে এই বিষয়ের অধীনে কয়েকটি উত্তর ব্যর্থ হয়। আপনি এটি আরও ভাল করে পরীক্ষা করে দেখুন।

যাইহোক আন্ডারস্কোরের প্রয়োজন নেই, যা কিছু লড্যাশ। আমি বিশ্বাস করি এটি খাঁটি জেএস ইএস 6 দিয়ে এটি করা উচিত, এটি যতটা কার্যকরী হয়।

এই কোডের টুকরোটি হ্রাস এবং নেস্টেড মানচিত্র ব্যবহার করে, কেবল দুটি অ্যারের কার্টেসিয়ান পণ্য পেতে তবে দ্বিতীয় অ্যারেটি কম ক্রমান্বিত একই ক্রিয়ায় পুনরাবৃত্ত কল থেকে আসে; অত: পর .. a[0].cartesian(...a.slice(1))

Array.prototype.cartesian = function(...a){
  return a.length ? this.reduce((p,c) => (p.push(...a[0].cartesian(...a.slice(1)).map(e => a.length > 1 ? [c,...e] : [c,e])),p),[])
                  : this;
};

var arr = ['a', 'b', 'c'],
    brr = [1,2,3],
    crr = [[9],[8],[7]];
console.log(JSON.stringify(arr.cartesian(brr,crr))); 


3

আমার নির্দিষ্ট সেটিংয়ে, "পুরানো ধাঁচের" পদ্ধতির আরও আধুনিক বৈশিষ্ট্যের উপর ভিত্তি করে পদ্ধতিগুলির চেয়ে বেশি দক্ষ বলে মনে হয়েছিল। নীচে কোডটি দেওয়া হয়েছে (@rsp এবং @sebnukem দ্বারা এই থ্রেডে পোস্ট করা অন্যান্য সমাধানগুলির সাথে একটি সামান্য তুলনা সহ) এটি অন্য কারও পক্ষেও কার্যকর প্রমাণিত হওয়া উচিত।

ধারণা অনুসরণ করা হয়। ধরা যাক আমরা Nঅ্যারেটির বাইরের পণ্যটি তৈরি করছি , a_1,...,a_Nযার প্রতিটিটির m_iউপাদান রয়েছে। এই অ্যারেগুলির বাইরের পণ্যগুলির M=m_1*m_2*...*m_Nউপাদান রয়েছে এবং আমরা তাদের প্রত্যেককে একটি N-মাত্রিক ভেক্টর দিয়ে সনাক্ত করতে পারি যেগুলির উপাদানগুলি ইতিবাচক পূর্ণসংখ্যার এবং - iতম উপাদানটি উপরের দিক থেকে কঠোরভাবে আবদ্ধ m_i। উদাহরণস্বরূপ, ভেক্টর (0, 0, ..., 0)সেই নির্দিষ্ট সংমিশ্রণের (m_1-1, m_2-1, ..., m_N-1)সাথে মিল রাখে যার মধ্যে প্রতিটি প্রতিটি অ্যারের থেকে প্রথম উপাদান নেয়, এবং সেই সংমিশ্রণের সাথে চিহ্নিত হয় যেখানে প্রতিটি অ্যারের থেকে শেষ উপাদান নেয়। এইভাবে সব নির্মাণ করার জন্যM সংমিশ্রণগুলি, নীচের ক্রিয়াটি ক্রমাগতভাবে এই জাতীয় সমস্ত ভেক্টর তৈরি করে এবং তাদের প্রত্যেকের জন্য ইনপুট অ্যারেগুলির উপাদানগুলির সংমিশ্রণটি চিহ্নিত করে।

function cartesianProduct(){
    const N = arguments.length;

    var arr_lengths = Array(N);
    var digits = Array(N);
    var num_tot = 1;
    for(var i = 0; i < N; ++i){
        const len = arguments[i].length;
        if(!len){
            num_tot = 0;
            break;
        }
        digits[i] = 0;
        num_tot *= (arr_lengths[i] = len);
    }

    var ret = Array(num_tot);
    for(var num = 0; num < num_tot; ++num){

        var item = Array(N);
        for(var j = 0; j < N; ++j){ item[j] = arguments[j][digits[j]]; }
        ret[num] = item;

        for(var idx = 0; idx < N; ++idx){
            if(digits[idx] == arr_lengths[idx]-1){
                digits[idx] = 0;
            }else{
                digits[idx] += 1;
                break;
            }
        }
    }
    return ret;
}
//------------------------------------------------------------------------------
let _f = (a, b) => [].concat(...a.map(a => b.map(b => [].concat(a, b))));
let cartesianProduct_rsp = (a, b, ...c) => b ? cartesianProduct_rsp(_f(a, b), ...c) : a;
//------------------------------------------------------------------------------
function cartesianProduct_sebnukem(a) {
    var i, j, l, m, a1, o = [];
    if (!a || a.length == 0) return a;

    a1 = a.splice(0, 1)[0];
    a = cartesianProduct_sebnukem(a);
    for (i = 0, l = a1.length; i < l; i++) {
        if (a && a.length) for (j = 0, m = a.length; j < m; j++)
            o.push([a1[i]].concat(a[j]));
        else
            o.push([a1[i]]);
    }
    return o;
}
//------------------------------------------------------------------------------
const L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
const args = [L, L, L, L, L, L];

let fns = {
    'cartesianProduct': function(args){ return cartesianProduct(...args); },
    'cartesianProduct_rsp': function(args){ return cartesianProduct_rsp(...args); },
    'cartesianProduct_sebnukem': function(args){ return cartesianProduct_sebnukem(args); }
};

Object.keys(fns).forEach(fname => {
    console.time(fname);
    const ret = fns[fname](args);
    console.timeEnd(fname);
});

সহ node v6.12.2, আমি নিম্নলিখিত সময় পাই:

cartesianProduct: 427.378ms
cartesianProduct_rsp: 1710.829ms
cartesianProduct_sebnukem: 593.351ms

3

যাদের জন্য টাইপস্ক্রিপ্টের প্রয়োজন (ডেমির উত্তর পুনরায় প্রয়োগ করা হয়েছে)

/**
 * Calculates "Cartesian Product" sets.
 * @example
 *   cartesianProduct([[1,2], [4,8], [16,32]])
 *   Returns:
 *   [
 *     [1, 4, 16],
 *     [1, 4, 32],
 *     [1, 8, 16],
 *     [1, 8, 32],
 *     [2, 4, 16],
 *     [2, 4, 32],
 *     [2, 8, 16],
 *     [2, 8, 32]
 *   ]
 * @see https://stackoverflow.com/a/36234242/1955709
 * @see https://en.wikipedia.org/wiki/Cartesian_product
 * @param arr {T[][]}
 * @returns {T[][]}
 */
function cartesianProduct<T> (arr: T[][]): T[][] {
  return arr.reduce((a, b) => {
    return a.map(x => {
      return b.map(y => {
        return x.concat(y)
      })
    }).reduce((c, d) => c.concat(d), [])
  }, [[]] as T[][])
}

2

অ্যারের ব্যবহার করে কেবলমাত্র একটি সাধারণ বাস্তব প্রয়োগের জন্য reduce:

const array1 = ["day", "month", "year", "time"];
const array2 = ["from", "to"];
const process = (one, two) => [one, two].join(" ");

const product = array1.reduce((result, one) => result.concat(array2.map(two => process(one, two))), []);

2

মাত্র কয়েকটি লাইনে আধুনিক জাভাস্ক্রিপ্ট। লোড্যাশের মতো কোনও বাহ্যিক গ্রন্থাগার বা নির্ভরতা নেই।

function cartesian(...arrays) {
  return arrays.reduce((a, b) => a.flatMap(x => b.map(y => x.concat([y]))), [ [] ]);
}

console.log(
  cartesian([1, 2], [10, 20], [100, 200, 300])
    .map(arr => JSON.stringify(arr))
    .join('\n')
);


2

আপনি reduce2D অ্যারে পারে । প্রতিটি লুপে সংমিশ্রণের সংখ্যা flatMapপেতে সংযোজক অ্যারে ব্যবহার করুন acc.length x curr.length[].concat(c, n)ব্যবহৃত হয় কারণ cপ্রথম পুনরাবৃত্তির একটি সংখ্যা এবং তারপরে একটি অ্যারে।

const data = [ [1, 2], [10, 20], [100, 200, 300] ];

const output = data.reduce((acc, curr) =>
  acc.flatMap(c => curr.map(n => [].concat(c, n)))
)

console.log(JSON.stringify(output))

(এটি নিনা স্কোলজের উত্তরের উপর ভিত্তি করে )


1

একটি পুনরাবৃত্তিমূলক পদ্ধতি যা ফলাফলগুলি ফলাফলগুলিতে আসলে যুক্ত করার আগে পণ্যগুলিকে ফিল্টার এবং সংশোধন করার ক্ষমতা যুক্ত করে। .ForEach এর চেয়ে .map এর ব্যবহারটি নোট করুন। কিছু ব্রাউজারগুলিতে .map দ্রুত চলে।

function crossproduct(arrays,rowtest,rowaction) {
      // Calculate the number of elements needed in the result
      var result_elems = 1, row_size = arrays.length;
      arrays.map(function(array) {
            result_elems *= array.length;
      });
      var temp = new Array(result_elems), result = [];

      // Go through each array and add the appropriate element to each element of the temp
      var scale_factor = result_elems;
      arrays.map(function(array)
      {
        var set_elems = array.length;
        scale_factor /= set_elems;
        for(var i=result_elems-1;i>=0;i--) {
            temp[i] = (temp[i] ? temp[i] : []);
            var pos = i / scale_factor % set_elems;
            // deal with floating point results for indexes, this took a little experimenting
            if(pos < 1 || pos % 1 <= .5) {
                pos = Math.floor(pos);
            } else {
                pos = Math.min(array.length-1,Math.ceil(pos));
            }
            temp[i].push(array[pos]);
            if(temp[i].length===row_size) {
                var pass = (rowtest ? rowtest(temp[i]) : true);
                if(pass) {
                    if(rowaction) {
                        result.push(rowaction(temp[i]));
                    } else {
                        result.push(temp[i]);
                    }
                }
            }
        }
      });
      return result;
    }

1

একটি সাধারণ "মন এবং দৃষ্টি আকর্ষণীয়" সমাধান।

এখানে চিত্র বর্ণনা লিখুন


// t = [i, length]

const moveThreadForwardAt = (t, tCursor) => {
  if (tCursor < 0)
    return true; // reached end of first array

  const newIndex = (t[tCursor][0] + 1) % t[tCursor][1];
  t[tCursor][0] = newIndex;

  if (newIndex == 0)
    return moveThreadForwardAt(t, tCursor - 1);

  return false;
}

const cartesianMult = (...args) => {
  let result = [];
  const t = Array.from(Array(args.length)).map((x, i) => [0, args[i].length]);
  let reachedEndOfFirstArray = false;

  while (false == reachedEndOfFirstArray) {
    result.push(t.map((v, i) => args[i][v[0]]));

    reachedEndOfFirstArray = moveThreadForwardAt(t, args.length - 1);
  }

  return result;
}

// cartesianMult(
//   ['a1', 'b1', 'c1'],
//   ['a2', 'b2'],
//   ['a3', 'b3', 'c3'],
//   ['a4', 'b4']
// );

console.log(cartesianMult(
  ['a1'],
  ['a2', 'b2'],
  ['a3', 'b3']
));

1

সরল জাভাস্ক্রিপ্টে @ ভাইবেলের কোডের একটি সহজ, পরিবর্তিত সংস্করণ:

function cartesianProduct(...arrays) {
  return arrays.reduce((a, b) => {
    return [].concat(...a.map(x => {
      const next = Array.isArray(x) ? x : [x];
      return [].concat(b.map(y => next.concat(...[y])));
    }));
  });
}

const product = cartesianProduct([1, 2], [10, 20], [100, 200, 300]);

console.log(product);
/*
[ [ 1, 10, 100 ],
  [ 1, 10, 200 ],
  [ 1, 10, 300 ],
  [ 1, 20, 100 ],
  [ 1, 20, 200 ],
  [ 1, 20, 300 ],
  [ 2, 10, 100 ],
  [ 2, 10, 200 ],
  [ 2, 10, 300 ],
  [ 2, 20, 100 ],
  [ 2, 20, 200 ],
  [ 2, 20, 300 ] ];
*/

1

আরও পঠনযোগ্য বাস্তবায়ন

function productOfTwo(one, two) {
  return one.flatMap(x => two.map(y => [].concat(x, y)));
}

function product(head = [], ...tail) {
  if (tail.length === 0) return head;
  return productOfTwo(head, product(...tail));
}

const test = product(
  [1, 2, 3],
  ['a', 'b']
);

console.log(JSON.stringify(test));


1
f=(a,b,c)=>a.flatMap(ai=>b.flatMap(bi=>c.map(ci=>[ai,bi,ci])))

এটি 3 অ্যারের জন্য।
কিছু উত্তর যে কোনও সংখ্যক অ্যারেয়ের জন্য একটি উপায় দিয়েছে।
এটি সহজেই কম বা বেশি অ্যারেতে চুক্তি বা প্রসারিত হতে পারে।
আমার পুনরাবৃত্তিগুলির সাথে একটি সেট সংমিশ্রণ প্রয়োজন, তাই আমি এটি ব্যবহার করতে পারতাম:

f(a,a,a)

তবে ব্যবহৃত:

f=(a,b,c)=>a.flatMap(a1=>a.flatMap(a2=>a.map(a3=>[a1,a2,a3])))

0

আমি লক্ষ্য করেছি যে কেউই এমন কোনও সমাধান পোস্ট করেন নি যা প্রতিটি সংশ্লেষ প্রক্রিয়া করার জন্য কোনও ফাংশনটি পাস করার অনুমতি দেয়, তাই আমার সমাধানটি এখানে:

const _ = require('lodash')

function combinations(arr, f, xArr = []) {
    return arr.length>1 
    ? _.flatMap(arr[0], x => combinations(arr.slice(1), f, xArr.concat(x)))
    : arr[0].map(x => f(...xArr.concat(x)))
}

// use case
const greetings = ["Hello", "Goodbye"]
const places = ["World", "Planet"]
const punctuationMarks = ["!", "?"]
combinations([greetings,places,punctuationMarks], (greeting, place, punctuationMark) => `${greeting} ${place}${punctuationMark}`)
  .forEach(row => console.log(row))

আউটপুট:

Hello World!
Hello World?
Hello Planet!
Hello Planet?
Goodbye World!
Goodbye World?
Goodbye Planet!
Goodbye Planet?

0

সরল জেএস ব্রুটে ফোর্স অ্যাপ্রোচ যা ইনপুট হিসাবে অ্যারের অ্যারে নেয়।

var cartesian = function(arrays) {
    var product = [];
    var precals = [];
    var length = arrays.reduce(function(acc, curr) {
        return acc * curr.length
    }, 1);
    for (var i = 0; i < arrays.length; i++) {
        var array = arrays[i];
        var mod = array.length;
        var div = i > 0 ? precals[i - 1].div * precals[i - 1].mod : 1;
        precals.push({
            div: div,
            mod: mod
        });
    }
    for (var j = 0; j < length; j++) {
        var item = [];
        for (var i = 0; i < arrays.length; i++) {
            var array = arrays[i];
            var precal = precals[i];
            var k = (~~(j / precal.div)) % precal.mod;
            item.push(array[k]);
        }
        product.push(item);
    }
    return product;
};

cartesian([
    [1],
    [2, 3]
]);

cartesian([
    [1],
    [2, 3],
    [4, 5, 6]
]);

0

var chars = ['A', 'B', 'C']
var nums = [1, 2, 3]

var cartesianProduct = function() {
  return _.reduce(arguments, function(a, b) {
    return _.flatten(_.map(a, function(x) {
      return _.map(b, function(y) {
        return x.concat(y);
      });
    }), true);
  }, [
    []
  ]);
};

console.log(cartesianProduct(chars, nums))
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

স্রেফ @ ডামারসেলের উত্তরটি কফস্ক্রিপ্ট থেকে জাভাস্ক্রিপ্টে রূপান্তরিত হয়েছে। এটা ঠিক কাজ করে।

var chars = ['A', 'B', 'C']
var nums = [1, 2, 3]

var cartesianProduct = function() {
  return _.reduce(arguments, function(a, b) {
    return _.flatten(_.map(a, function(x) {
      return _.map(b, function(y) {
        return x.concat(y);
      });
    }), true);
  }, [[]]);
};

console.log( cartesianProduct(chars, nums) )

0

তবুও আরেকটি বাস্তবায়ন। স্বল্পতম বা অভিনব নয়, তবে দ্রুত:

function cartesianProduct() {
    var arr = [].slice.call(arguments),
        intLength = arr.length,
        arrHelper = [1],
        arrToReturn = [];

    for (var i = arr.length - 1; i >= 0; i--) {
        arrHelper.unshift(arrHelper[0] * arr[i].length);
    }

    for (var i = 0, l = arrHelper[0]; i < l; i++) {
        arrToReturn.push([]);
        for (var j = 0; j < intLength; j++) {
            arrToReturn[i].push(arr[j][(i / arrHelper[j + 1] | 0) % arr[j].length]);
        }
    }

    return arrToReturn;
}

0

কোন গ্রন্থাগার প্রয়োজন! :)

তীর ফাংশন প্রয়োজন যদিও এবং সম্ভবত এটি দক্ষ নয় that : /

const flatten = (xs) => 
    xs.flat(Infinity)

const binaryCartesianProduct = (xs, ys) =>
    xs.map((xi) => ys.map((yi) => [xi, yi])).flat()

const cartesianProduct = (...xss) =>
    xss.reduce(binaryCartesianProduct, [[]]).map(flatten)
      
console.log(cartesianProduct([1,2,3], [1,2,3], [1,2,3]))


0

রেকর্ড এর জন্য

এখানে এটি আমার সংস্করণে যায়। আমি "()" এর জন্য সহজ জাভাস্ক্রিপ্ট পুনরায় ব্যবহারকারীর সাহায্যে এটি তৈরি করেছি, সুতরাং এটি প্রতিটি ক্ষেত্রে উপযুক্ত এবং এতে সেরা পারফরম্যান্স রয়েছে।

function cartesian(arrays){
    var quant = 1, counters = [], retArr = [];

    // Counts total possibilities and build the counters Array;
    for(var i=0;i<arrays.length;i++){
        counters[i] = 0;
        quant *= arrays[i].length;
    }

    // iterate all possibilities
    for(var i=0,nRow;i<quant;i++){
        nRow = [];
        for(var j=0;j<counters.length;j++){
            if(counters[j] < arrays[j].length){
                nRow.push(arrays[j][counters[j]]);
            } else { // in case there is no such an element it restarts the current counter
                counters[j] = 0;
                nRow.push(arrays[j][counters[j]]);
            }
            counters[j]++;
        }
        retArr.push(nRow);
    }
    return retArr;
}

শুভেচ্ছান্তে.

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.