Ruby elementlar tartibidan qat'i nazar bir nechta (ikki martadan ortiq) qatorlar mosligini tekshiring

Agar ikkita katalog bo'lsa, a va b . Men ularni a.uniq.sort == b.uniq.sort deb solishtirishim mumkin. Bu a elementlari b da mos keladimi yoki yo'qligini bildiradi.

Agar a, b, c, d to'rt qatorlari bo'lsa nima qilishim kerak? Men ularning bir-biriga teng ekanligiga ishonch hosil qilishim kerak. Buning eng yaxshi yo'li qanday?

1

6 javoblar

Bitta qatorni oling, uni noyob elementlarni tartiblang va boshqa qatorlarni mos yozuvlar bilan solishtiring. Bir-biriga teng bo'lmasa, noto'g'ri ko'rsatma.

ars = [a,b,c,d]
ref = ars.pop.uniq.sort #take care: pop mutates ars
p ars.all?{|ar| ar.uniq.sort == ref}
3
qo'shib qo'ydi
Ha, yoki ars.map (?: Sort) .uniq.size == 1 bo'lsa-da, bu sizning qisqa muddatli xususiyatiga ega emas.
qo'shib qo'ydi muallif Cary Swoveland, manba
Dastlabki qatorni ushlab qolmaslik uchun ars [0] , ars [1 ..- 1] dan foydalanishingiz mumkin.
qo'shib qo'ydi muallif mdesantis, manba
[%w[a b c], %w[c b a], %w[a a b c], %w[b a b c]]
.group_by{|a| a.uniq.sort}.one? # => true

[%w[a b c], %w[c b a], %w[a a b c], %w[b a b c d]]
.group_by{|a| a.uniq.sort}.one? # => false
2
qo'shib qo'ydi
Yahshisi! group_by tuyg'usi bor edi, lekin toza echim keltiradi, ammo men buni o'tkazib yubordim!
qo'shib qo'ydi muallif mdesantis, manba

Tartiblashni o'z ichiga olmaydi.

arr berilgan qatorlardan iborat bo'lsin. Agar massivlar dublikatlar bo'lmasa, bu oddiy bo'lar edi:

first, *rest = arr
rest.all? { |a| (first-a).empty? && (a-first).empty? }

Ikki nusxadagi ma'lumotlar bilan ishlash uchun Array # difference yordamchisini belgilab olamiz:

class Array
  def difference(other)
    h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
    reject { |e| h[e] > 0 && h[e] -= 1 }
  end
end

Qisqasi, n qatori elementlari a bir ob'ektga teng va b qatorining m elementlariga teng bo'lsa, a qatorlari a [nm, 0] .max elementlarini o'z ichiga oladi (birinchi a.difference (b) ob'ektga teng.

Keyin biz quyidagilarni yozishimiz mumkin.

first, *rest = arr
rest.all? { |a| first.difference(a).empty? && a.difference(first).empty? }

a elementining har bir elementi birinchi noyob elementiga xaritada bo'lsa va bloknota bo'lsa, blok true qiymatini baholaydi.

Faqatgina bitta muammo uchun Array # difference yaratish uchun vaqt yo'qotilgan kabi ko'rinishi mumkin. Biroq, keng qo'llanishga ega bo'lgan asboblar to'plamimning qimmatli a'zosi bo'lishini topdim, shuning uchun men uni ruby yadrosi ga qo'shiladi. Bog'dan foydalanishda misollar keltirib chiqadi, shuningdek, SO ga javob berishni o'z ichiga oladi, bu esa u dasturni topgan muammolarning yana uzoq ro'yxatini o'z ichiga oladi.

2
qo'shib qo'ydi

Yaxshi reduce echimini topamiz:

ars.reduce { |a, v| a.uniq.sort == v.uniq.sort ? v.uniq.sort : break }

Qaysi kod map bilan birgalikda ishlatiladigan juda toza kodga tugaydi:

ars.map { |v| v.uniq.sort }.reduce { |a, v| a == v ? v : break }

The map -> reduce version is not the the best for performance since all the array elements get uniq.sort'd, but it's readable and functional style.

1
qo'shib qo'ydi

Siz quyidagilarni sinashingiz mumkin:

a.uniq.sort == b.uniq.sort and b.uniq.sort == c.uniq.sort and c.uniq.sort == d.uniq.sort 

Uni optimallashtirish uchun siz taqqoslashdan oldin qayta hisoblashni oldini olish uchun b.uniq.sort va c.uniq.sort natijalarini saqlashingiz mumkin.

1
qo'shib qo'ydi
Bu farqlanmaydi ... Agar 10 ta massiv mavjud bo'lsa? yoki 15 kishi?
qo'shib qo'ydi muallif Zack, manba
Buni ko'rib chiqish uchun javob yozildi
qo'shib qo'ydi muallif utsav_deep, manba

Agar uniqdan foydalansangiz, kesishuvdan foydalanishingiz mumkin, uniq kesishmasdan esa, massivlarni taqqoslashda foydalanilmaydi.

arr.inject(:&).sort == arr.first.uniq.sort

Bu shunga o'xshash qatorlarni anglatadi

[3,2,3,1]
[1,3,2]
[3,2,1]
[2,1,3,1]

bir xil bo'ladi

0
qo'shib qo'ydi